~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to storage/innobase/fsp/fsp0fsp.c

  • Committer: Jay Pipes
  • Date: 2009-03-13 23:35:46 UTC
  • mto: This revision was merged to the branch mainline in revision 937.
  • Revision ID: jpipes@serialcoder-20090313233546-n12t6xpf71um75fo
Split index hints out into their own file, removal from sql_lex.h and sql_select.cc

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/*****************************************************************************
2
 
 
3
 
Copyright (c) 1995, 2010, Innobase Oy. 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 as published by the Free Software
7
 
Foundation; version 2 of the License.
8
 
 
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.
12
 
 
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
16
 
 
17
 
*****************************************************************************/
18
 
 
19
 
/******************************************************************//**
20
 
@file fsp/fsp0fsp.c
 
1
/**********************************************************************
21
2
File space management
22
3
 
 
4
(c) 1995 Innobase Oy
 
5
 
23
6
Created 11/29/1995 Heikki Tuuri
24
7
***********************************************************************/
25
8
 
31
14
 
32
15
#include "buf0buf.h"
33
16
#include "fil0fil.h"
 
17
#include "sync0sync.h"
34
18
#include "mtr0log.h"
 
19
#include "fut0fut.h"
35
20
#include "ut0byte.h"
36
 
#include "page0page.h"
 
21
#include "srv0srv.h"
37
22
#include "page0zip.h"
38
 
#ifdef UNIV_HOTBACKUP
39
 
# include "fut0lst.h"
40
 
#else /* UNIV_HOTBACKUP */
41
 
# include "sync0sync.h"
42
 
# include "fut0fut.h"
43
 
# include "srv0srv.h"
44
 
# include "ibuf0ibuf.h"
45
 
# include "btr0btr.h"
46
 
# include "btr0sea.h"
47
 
# include "dict0boot.h"
48
 
# include "log0log.h"
49
 
#endif /* UNIV_HOTBACKUP */
 
23
#include "ibuf0ibuf.h"
 
24
#include "btr0btr.h"
 
25
#include "btr0sea.h"
 
26
#include "dict0boot.h"
50
27
#include "dict0mem.h"
 
28
#include "log0log.h"
51
29
 
52
30
 
53
31
#define FSP_HEADER_OFFSET       FIL_PAGE_DATA   /* Offset of the space header
127
105
 
128
106
#define FSEG_ARR_OFFSET         (FSEG_PAGE_DATA + FLST_NODE_SIZE)
129
107
/*-------------------------------------*/
130
 
#define FSEG_ID                 0       /* 8 bytes of segment id: if this is 0,
131
 
                                        it means that the header is unused */
 
108
#define FSEG_ID                 0       /* 8 bytes of segment id: if this is
 
109
                                        ut_dulint_zero, it means that the
 
110
                                        header is unused */
132
111
#define FSEG_NOT_FULL_N_USED    8
133
112
                                        /* number of used segment pages in
134
113
                                        the FSEG_NOT_FULL list */
230
209
/* Offset of the descriptor array on a descriptor page */
231
210
#define XDES_ARR_OFFSET         (FSP_HEADER_OFFSET + FSP_HEADER_SIZE)
232
211
 
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;
236
 
 
237
 
/**********************************************************************//**
 
212
/**************************************************************************
238
213
Returns an extent to the free list of a space. */
239
214
static
240
215
void
241
216
fsp_free_extent(
242
217
/*============*/
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. */
250
225
static
251
226
void
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. */
264
238
static
265
239
ulint
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
274
248
segment. */
275
249
static
276
250
void
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
288
 
-> FSEG_FREE.
289
 
@return the first extent descriptor, or NULL if none */
 
262
-> FSEG_FREE. */
290
263
static
291
264
xdes_t*
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
 
268
                                none */
 
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
305
280
void
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
319
 
fragmentation.
320
 
@return the allocated page number, FIL_NULL if no page could be allocated */
 
294
fragmentation. */
321
295
static
322
296
ulint
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 */
337
 
 
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 */
 
312
 
 
313
 
 
314
/**************************************************************************
 
315
Reads the file space size stored in the header page. */
341
316
UNIV_INTERN
342
317
ulint
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) */
346
322
{
347
323
        return(mach_read_from_4(page + FSP_HEADER_OFFSET + FSP_SIZE));
348
324
}
349
325
 
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. */
354
328
UNIV_INLINE
355
329
fsp_header_t*
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 */
362
337
{
363
338
        buf_block_t*    block;
364
339
        fsp_header_t*   header;
378
353
        return(header);
379
354
}
380
355
 
381
 
/**********************************************************************//**
382
 
Gets a descriptor bit of a page.
383
 
@return TRUE if free */
 
356
/**************************************************************************
 
357
Gets a descriptor bit of a page. */
384
358
UNIV_INLINE
385
359
ibool
386
360
xdes_get_bit(
387
361
/*=========*/
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 */
393
368
{
394
369
        ulint   index;
395
370
        ulint   byte_index;
409
384
                              bit_index));
410
385
}
411
386
 
412
 
/**********************************************************************//**
 
387
/**************************************************************************
413
388
Sets a descriptor bit of a page. */
414
389
UNIV_INLINE
415
390
void
416
391
xdes_set_bit(
417
392
/*=========*/
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 */
424
399
{
425
400
        ulint   index;
426
401
        ulint   byte_index;
444
419
                         MLOG_1BYTE, mtr);
445
420
}
446
421
 
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. */
452
426
UNIV_INLINE
453
427
ulint
454
428
xdes_find_bit(
455
429
/*==========*/
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
 
431
                        found */
 
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 */
461
437
{
462
438
        ulint   i;
463
439
 
482
458
        return(ULINT_UNDEFINED);
483
459
}
484
460
 
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. */
489
464
UNIV_INLINE
490
465
ulint
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
 
469
                        found */
 
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 */
498
475
{
499
476
        ulint   i;
500
477
 
519
496
        return(ULINT_UNDEFINED);
520
497
}
521
498
 
522
 
/**********************************************************************//**
523
 
Returns the number of used pages in a descriptor.
524
 
@return number of pages used */
 
499
/**************************************************************************
 
500
Returns the number of used pages in a descriptor. */
525
501
UNIV_INLINE
526
502
ulint
527
503
xdes_get_n_used(
528
504
/*============*/
529
 
        const xdes_t*   descr,  /*!< in: descriptor */
530
 
        mtr_t*          mtr)    /*!< in: mtr */
 
505
                        /* out: number of pages used */
 
506
        xdes_t* descr,  /* in: descriptor */
 
507
        mtr_t*  mtr)    /* in: mtr */
531
508
{
532
509
        ulint   i;
533
510
        ulint   count   = 0;
543
520
        return(count);
544
521
}
545
522
 
546
 
/**********************************************************************//**
547
 
Returns true if extent contains no used pages.
548
 
@return TRUE if totally free */
 
523
/**************************************************************************
 
524
Returns true if extent contains no used pages. */
549
525
UNIV_INLINE
550
526
ibool
551
527
xdes_is_free(
552
528
/*=========*/
553
 
        const xdes_t*   descr,  /*!< in: descriptor */
554
 
        mtr_t*          mtr)    /*!< in: mtr */
 
529
                        /* out: TRUE if totally free */
 
530
        xdes_t* descr,  /* in: descriptor */
 
531
        mtr_t*  mtr)    /* in: mtr */
555
532
{
556
533
        if (0 == xdes_get_n_used(descr, mtr)) {
557
534
 
561
538
        return(FALSE);
562
539
}
563
540
 
564
 
/**********************************************************************//**
565
 
Returns true if extent contains no free pages.
566
 
@return TRUE if full */
 
541
/**************************************************************************
 
542
Returns true if extent contains no free pages. */
567
543
UNIV_INLINE
568
544
ibool
569
545
xdes_is_full(
570
546
/*=========*/
571
 
        const xdes_t*   descr,  /*!< in: descriptor */
572
 
        mtr_t*          mtr)    /*!< in: mtr */
 
547
                        /* out: TRUE if full */
 
548
        xdes_t* descr,  /* in: descriptor */
 
549
        mtr_t*  mtr)    /* in: mtr */
573
550
{
574
551
        if (FSP_EXTENT_SIZE == xdes_get_n_used(descr, mtr)) {
575
552
 
579
556
        return(FALSE);
580
557
}
581
558
 
582
 
/**********************************************************************//**
 
559
/**************************************************************************
583
560
Sets the state of an xdes. */
584
561
UNIV_INLINE
585
562
void
586
563
xdes_set_state(
587
564
/*===========*/
588
 
        xdes_t* descr,  /*!< in/out: descriptor */
589
 
        ulint   state,  /*!< in: state to set */
590
 
        mtr_t*  mtr)    /*!< in: mtr handle */
 
565
        xdes_t* descr,  /* in: descriptor */
 
566
        ulint   state,  /* in: state to set */
 
567
        mtr_t*  mtr)    /* in: mtr handle */
591
568
{
592
569
        ut_ad(descr && mtr);
593
570
        ut_ad(state >= XDES_FREE);
597
574
        mlog_write_ulint(descr + XDES_STATE, state, MLOG_4BYTES, mtr);
598
575
}
599
576
 
600
 
/**********************************************************************//**
601
 
Gets the state of an xdes.
602
 
@return state */
 
577
/**************************************************************************
 
578
Gets the state of an xdes. */
603
579
UNIV_INLINE
604
580
ulint
605
581
xdes_get_state(
606
582
/*===========*/
607
 
        const xdes_t*   descr,  /*!< in: descriptor */
608
 
        mtr_t*          mtr)    /*!< in: mtr handle */
 
583
                        /* out: state */
 
584
        xdes_t* descr,  /* in: descriptor */
 
585
        mtr_t*  mtr)    /* in: mtr handle */
609
586
{
610
587
        ulint   state;
611
588
 
617
594
        return(state);
618
595
}
619
596
 
620
 
/**********************************************************************//**
 
597
/**************************************************************************
621
598
Inits an extent descriptor to the free and clean state. */
622
599
UNIV_INLINE
623
600
void
624
601
xdes_init(
625
602
/*======*/
626
 
        xdes_t* descr,  /*!< in: descriptor */
627
 
        mtr_t*  mtr)    /*!< in: mtr */
 
603
        xdes_t* descr,  /* in: descriptor */
 
604
        mtr_t*  mtr)    /* in: mtr */
628
605
{
629
606
        ulint   i;
630
607
 
639
616
        xdes_set_state(descr, XDES_FREE, mtr);
640
617
}
641
618
 
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. */
645
621
UNIV_INLINE
646
622
ulint
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 */
652
629
{
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
656
 
#  error
657
 
# endif
658
 
# if PAGE_ZIP_MIN_SIZE <= XDES_ARR_OFFSET \
 
632
# error
 
633
#endif
 
634
#if PAGE_ZIP_MIN_SIZE <= XDES_ARR_OFFSET \
659
635
                + (PAGE_ZIP_MIN_SIZE / FSP_EXTENT_SIZE) * XDES_SIZE
660
 
#  error
661
 
# endif
662
 
#endif /* !DOXYGEN */
 
636
# error
 
637
#endif
663
638
        ut_ad(ut_is_2pow(zip_size));
664
639
 
665
640
        if (!zip_size) {
671
646
        }
672
647
}
673
648
 
674
 
/********************************************************************//**
675
 
Calculates the descriptor index within a descriptor page.
676
 
@return descriptor index */
 
649
/************************************************************************
 
650
Calculates the descriptor index within a descriptor page. */
677
651
UNIV_INLINE
678
652
ulint
679
653
xdes_calc_descriptor_index(
680
654
/*=======================*/
681
 
        ulint   zip_size,       /*!< in: compressed page size in bytes;
 
655
                                /* out: descriptor index */
 
656
        ulint   zip_size,       /* in: compressed page size in bytes;
682
657
                                0 for uncompressed pages */
683
 
        ulint   offset)         /*!< in: page offset */
 
658
        ulint   offset)         /* in: page offset */
684
659
{
685
660
        ut_ad(ut_is_2pow(zip_size));
686
661
 
692
667
        }
693
668
}
694
669
 
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. */
703
676
UNIV_INLINE
704
677
xdes_t*
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 */
714
690
{
715
691
        ulint   limit;
716
692
        ulint   size;
763
739
               + XDES_SIZE * xdes_calc_descriptor_index(zip_size, offset));
764
740
}
765
741
 
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. */
775
749
static
776
750
xdes_t*
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
 
755
                        limit */
 
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 */
785
762
{
786
763
        buf_block_t*    block;
787
764
        fsp_header_t*   sp_header;
794
771
                                                  mtr));
795
772
}
796
773
 
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. */
802
778
UNIV_INLINE
803
779
xdes_t*
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 */
812
789
{
813
790
        xdes_t* descr;
814
791
 
821
798
        return(descr);
822
799
}
823
800
 
824
 
/********************************************************************//**
825
 
Returns page offset of the first page in extent described by a descriptor.
826
 
@return offset of the first page in extent */
 
801
/************************************************************************
 
802
Returns page offset of the first page in extent described by a descriptor. */
827
803
UNIV_INLINE
828
804
ulint
829
805
xdes_get_offset(
830
806
/*============*/
831
 
        xdes_t* descr)  /*!< in: extent descriptor */
 
807
                        /* out: offset of the first page in extent */
 
808
        xdes_t* descr)  /* in: extent descriptor */
832
809
{
833
810
        ut_ad(descr);
834
811
 
836
813
               + ((page_offset(descr) - XDES_ARR_OFFSET) / XDES_SIZE)
837
814
               * FSP_EXTENT_SIZE);
838
815
}
839
 
#endif /* !UNIV_HOTBACKUP */
840
816
 
841
 
/***********************************************************//**
 
817
/***************************************************************
842
818
Inits a file page whose prior contents should be ignored. */
843
819
static
844
820
void
845
821
fsp_init_file_page_low(
846
822
/*===================*/
847
 
        buf_block_t*    block)  /*!< in: pointer to a page */
 
823
        buf_block_t*    block)  /* in: pointer to a page */
848
824
{
849
825
        page_t*         page    = buf_block_get_frame(block);
850
826
        page_zip_des_t* page_zip= buf_block_get_page_zip(block);
851
827
 
852
 
#ifndef UNIV_HOTBACKUP
853
828
        block->check_index_page_at_flush = FALSE;
854
 
#endif /* !UNIV_HOTBACKUP */
855
829
 
856
830
        if (UNIV_LIKELY_NULL(page_zip)) {
857
831
                memset(page, 0, UNIV_PAGE_SIZE);
868
842
                return;
869
843
        }
870
844
 
871
 
        memset(page, 0, UNIV_PAGE_SIZE);
 
845
#ifdef UNIV_BASIC_LOG_DEBUG
 
846
        memset(page, 0xff, UNIV_PAGE_SIZE);
 
847
#endif
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);
875
853
}
876
854
 
877
 
#ifndef UNIV_HOTBACKUP
878
 
/***********************************************************//**
 
855
/***************************************************************
879
856
Inits a file page whose prior contents should be ignored. */
880
857
static
881
858
void
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 */
886
863
{
887
864
        fsp_init_file_page_low(block);
888
865
 
889
866
        mlog_write_initial_log_record(buf_block_get_frame(block),
890
867
                                      MLOG_INIT_FILE_PAGE, mtr);
891
868
}
892
 
#endif /* !UNIV_HOTBACKUP */
893
869
 
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. */
897
872
UNIV_INTERN
898
873
byte*
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 */
904
880
{
905
881
        ut_ad(ptr && end_ptr);
906
882
 
911
887
        return(ptr);
912
888
}
913
889
 
914
 
/**********************************************************************//**
 
890
/**************************************************************************
915
891
Initializes the fsp system. */
916
892
UNIV_INTERN
917
893
void
921
897
        /* Does nothing at the moment */
922
898
}
923
899
 
924
 
/**********************************************************************//**
 
900
/**************************************************************************
925
901
Writes the space id and compressed page size to a tablespace header.
926
902
This function is used past the buffer pool when we in fil0fil.c create
927
903
a new single-table tablespace. */
929
905
void
930
906
fsp_header_init_fields(
931
907
/*===================*/
932
 
        page_t* page,           /*!< in/out: first page in the space */
933
 
        ulint   space_id,       /*!< in: space id */
934
 
        ulint   flags)          /*!< in: tablespace flags (FSP_SPACE_FLAGS):
 
908
        page_t* page,           /* in/out: first page in the space */
 
909
        ulint   space_id,       /* in: space id */
 
910
        ulint   flags)          /* in: tablespace flags (FSP_SPACE_FLAGS):
935
911
                                0, or table->flags if newer than COMPACT */
936
912
{
937
913
        /* The tablespace flags (FSP_SPACE_FLAGS) should be 0 for
946
922
                        flags);
947
923
}
948
924
 
949
 
#ifndef UNIV_HOTBACKUP
950
 
/**********************************************************************//**
 
925
/**************************************************************************
951
926
Initializes the space header of a new created space and creates also the
952
927
insert buffer tree root if space == 0. */
953
928
UNIV_INTERN
954
929
void
955
930
fsp_header_init(
956
931
/*============*/
957
 
        ulint   space,          /*!< in: space id */
958
 
        ulint   size,           /*!< in: current size in blocks */
959
 
        mtr_t*  mtr)            /*!< in: mini-transaction handle */
 
932
        ulint   space,          /* in: space id */
 
933
        ulint   size,           /* in: current size in blocks */
 
934
        mtr_t*  mtr)            /* in: mini-transaction handle */
960
935
{
961
936
        fsp_header_t*   header;
962
937
        buf_block_t*    block;
998
973
        flst_init(header + FSP_SEG_INODES_FULL, mtr);
999
974
        flst_init(header + FSP_SEG_INODES_FREE, mtr);
1000
975
 
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);
1007
982
        } else {
1008
983
                fsp_fill_free_list(TRUE, space, header, mtr);
1009
984
        }
1010
985
}
1011
 
#endif /* !UNIV_HOTBACKUP */
1012
986
 
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. */
1016
989
UNIV_INTERN
1017
990
ulint
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 */
1021
995
{
1022
996
        ulint   fsp_id;
1023
997
        ulint   id;
1038
1012
        return(id);
1039
1013
}
1040
1014
 
1041
 
/**********************************************************************//**
1042
 
Reads the space flags from the first page of a tablespace.
1043
 
@return flags */
 
1015
/**************************************************************************
 
1016
Reads the space flags from the first page of a tablespace. */
1044
1017
UNIV_INTERN
1045
1018
ulint
1046
1019
fsp_header_get_flags(
1047
1020
/*=================*/
1048
 
        const page_t*   page)   /*!< in: first page of a tablespace */
 
1021
                                /* out: flags */
 
1022
        const page_t*   page)   /* in: first page of a tablespace */
1049
1023
{
1050
1024
        ut_ad(!page_offset(page));
1051
1025
 
1052
1026
        return(mach_read_from_4(FSP_HEADER_OFFSET + FSP_SPACE_FLAGS + page));
1053
1027
}
1054
1028
 
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. */
1058
1031
UNIV_INTERN
1059
1032
ulint
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 */
1063
1038
{
1064
1039
        ulint   flags = fsp_header_get_flags(page);
1065
1040
 
1066
1041
        return(dict_table_flags_to_zip_size(flags));
1067
1042
}
1068
1043
 
1069
 
#ifndef UNIV_HOTBACKUP
1070
 
/**********************************************************************//**
 
1044
/**************************************************************************
1071
1045
Increases the space size field of a space. */
1072
1046
UNIV_INTERN
1073
1047
void
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 */
1079
1053
{
1080
1054
        fsp_header_t*   header;
1081
1055
        ulint           size;
1095
1069
                         mtr);
1096
1070
}
1097
1071
 
1098
 
/**********************************************************************//**
 
1072
/**************************************************************************
1099
1073
Gets the current free limit of the system tablespace.  The free limit
1100
1074
means the place of the first page which has never been put to the the
1101
1075
free list for allocation.  The space above that address is initialized
1102
 
to zero.  Sets also the global variable log_fsp_current_free_limit.
1103
 
@return free limit in megabytes */
 
1076
to zero.  Sets also the global variable log_fsp_current_free_limit. */
1104
1077
UNIV_INTERN
1105
1078
ulint
1106
1079
fsp_header_get_free_limit(void)
1107
1080
/*===========================*/
 
1081
                        /* out: free limit in megabytes */
1108
1082
{
1109
1083
        fsp_header_t*   header;
1110
1084
        ulint           limit;
1127
1101
        return(limit);
1128
1102
}
1129
1103
 
1130
 
/**********************************************************************//**
 
1104
/**************************************************************************
1131
1105
Gets the size of the system tablespace from the tablespace header.  If
1132
1106
we do not have an auto-extending data file, this should be equal to
1133
1107
the size of the data files.  If there is an auto-extending data file,
1134
 
this can be smaller.
1135
 
@return size in pages */
 
1108
this can be smaller. */
1136
1109
UNIV_INTERN
1137
1110
ulint
1138
1111
fsp_header_get_tablespace_size(void)
1139
1112
/*================================*/
 
1113
                        /* out: size in pages */
1140
1114
{
1141
1115
        fsp_header_t*   header;
1142
1116
        ulint           size;
1155
1129
        return(size);
1156
1130
}
1157
1131
 
1158
 
/***********************************************************************//**
 
1132
/***************************************************************************
1159
1133
Tries to extend a single-table tablespace so that a page would fit in the
1160
 
data file.
1161
 
@return TRUE if success */
 
1134
data file. */
1162
1135
static
1163
1136
ibool
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 */
1170
1144
{
1171
1145
        ibool   success;
1172
1146
        ulint   actual_size;
1188
1162
        return(success);
1189
1163
}
1190
1164
 
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. */
1194
1167
static
1195
1168
ibool
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
1202
1176
                                        megabyte */
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 */
1206
1180
{
1207
1181
        ulint   size;
1208
1182
        ulint   zip_size;
1216
1190
 
1217
1191
        if (space == 0 && !srv_auto_extend_last_data_file) {
1218
1192
 
1219
 
                /* We print the error message only once to avoid
1220
 
                spamming the error log. Note that we don't need
1221
 
                to reset the flag to FALSE as dealing with this
1222
 
                error requires server restart. */
1223
 
                if (fsp_tbs_full_error_printed == FALSE) {
1224
 
                        fprintf(stderr,
1225
 
                                "InnoDB: Error: Data file(s) ran"
1226
 
                                " out of space.\n"
1227
 
                                "Please add another data file or"
1228
 
                                " use \'autoextend\' for the last"
1229
 
                                " data file.\n");
1230
 
                        fsp_tbs_full_error_printed = TRUE;
1231
 
                }
1232
1193
                return(FALSE);
1233
1194
        }
1234
1195
 
1264
1225
                at a time, but for bigger tablespaces more. It is not
1265
1226
                enough to extend always by one extent, because some
1266
1227
                extents are frag page extents. */
1267
 
                ulint   extent_size;    /*!< one megabyte, in pages */
 
1228
                ulint   extent_size;    /* one megabyte, in pages */
1268
1229
 
1269
1230
                if (!zip_size) {
1270
1231
                        extent_size = FSP_EXTENT_SIZE;
1323
1284
        return(TRUE);
1324
1285
}
1325
1286
 
1326
 
/**********************************************************************//**
 
1287
/**************************************************************************
1327
1288
Puts new extents to the free list if there are free extents above the free
1328
1289
limit. If an extent happens to contain an extent descriptor page, the extent
1329
1290
is put to the FSP_FREE_FRAG list with the page marked as used. */
1331
1292
void
1332
1293
fsp_fill_free_list(
1333
1294
/*===============*/
1334
 
        ibool           init_space,     /*!< in: TRUE if this is a single-table
 
1295
        ibool           init_space,     /* in: TRUE if this is a single-table
1335
1296
                                        tablespace and we are only initing
1336
1297
                                        the tablespace's first extent
1337
1298
                                        descriptor page and ibuf bitmap page;
1338
1299
                                        then we do not allocate more extents */
1339
 
        ulint           space,          /*!< in: space */
1340
 
        fsp_header_t*   header,         /*!< in/out: space header */
1341
 
        mtr_t*          mtr)            /*!< in: mtr */
 
1300
        ulint           space,          /* in: space */
 
1301
        fsp_header_t*   header,         /* in: space header */
 
1302
        mtr_t*          mtr)            /* in: mtr */
1342
1303
{
1343
1304
        ulint   limit;
1344
1305
        ulint   size;
1486
1447
        }
1487
1448
}
1488
1449
 
1489
 
/**********************************************************************//**
1490
 
Allocates a new free extent.
1491
 
@return extent descriptor, NULL if cannot be allocated */
 
1450
/**************************************************************************
 
1451
Allocates a new free extent. */
1492
1452
static
1493
1453
xdes_t*
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
 
1457
                        allocated */
 
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 */
1503
1465
{
1504
1466
        fsp_header_t*   header;
1505
1467
        fil_addr_t      first;
1536
1498
        return(descr);
1537
1499
}
1538
1500
 
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. */
1542
1503
static
1543
1504
ulint
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
 
1508
                        be allocated */
 
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 */
1551
1514
{
1552
1515
        fsp_header_t*   header;
1553
1516
        fil_addr_t      first;
1677
1640
        return(page_no);
1678
1641
}
1679
1642
 
1680
 
/**********************************************************************//**
 
1643
/**************************************************************************
1681
1644
Frees a single page of a space. The page is marked as free and clean. */
1682
1645
static
1683
1646
void
1684
1647
fsp_free_page(
1685
1648
/*==========*/
1686
 
        ulint   space,  /*!< in: space id */
1687
 
        ulint   zip_size,/*!< in: compressed page size in bytes
 
1649
        ulint   space,  /* in: space id */
 
1650
        ulint   zip_size,/* in: compressed page size in bytes
1688
1651
                        or 0 for uncompressed pages */
1689
 
        ulint   page,   /*!< in: page offset */
1690
 
        mtr_t*  mtr)    /*!< in: mtr handle */
 
1652
        ulint   page,   /* in: page offset */
 
1653
        mtr_t*  mtr)    /* in: mtr handle */
1691
1654
{
1692
1655
        fsp_header_t*   header;
1693
1656
        xdes_t*         descr;
1767
1730
        }
1768
1731
}
1769
1732
 
1770
 
/**********************************************************************//**
 
1733
/**************************************************************************
1771
1734
Returns an extent to the free list of a space. */
1772
1735
static
1773
1736
void
1774
1737
fsp_free_extent(
1775
1738
/*============*/
1776
 
        ulint   space,  /*!< in: space id */
1777
 
        ulint   zip_size,/*!< in: compressed page size in bytes
 
1739
        ulint   space,  /* in: space id */
 
1740
        ulint   zip_size,/* in: compressed page size in bytes
1778
1741
                        or 0 for uncompressed pages */
1779
 
        ulint   page,   /*!< in: page offset in the extent */
1780
 
        mtr_t*  mtr)    /*!< in: mtr */
 
1742
        ulint   page,   /* in: page offset in the extent */
 
1743
        mtr_t*  mtr)    /* in: mtr */
1781
1744
{
1782
1745
        fsp_header_t*   header;
1783
1746
        xdes_t*         descr;
1801
1764
        flst_add_last(header + FSP_FREE, descr + XDES_FLST_NODE, mtr);
1802
1765
}
1803
1766
 
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. */
1807
1769
UNIV_INLINE
1808
1770
fseg_inode_t*
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 */
1817
1780
{
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);
1822
1785
}
1823
1786
 
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. */
1827
1789
static
1828
1790
ulint
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
 
1794
                        if not found */
 
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 */
1834
1798
{
1835
1799
        ulint           i;
1836
1800
        fseg_inode_t*   inode;
1840
1804
                inode = fsp_seg_inode_page_get_nth_inode(
1841
1805
                        page, i, zip_size, mtr);
1842
1806
 
1843
 
                if (mach_read_from_8(inode + FSEG_ID)) {
 
1807
                if (!ut_dulint_is_zero(mach_read_from_8(inode + FSEG_ID))) {
1844
1808
                        /* This is used */
1845
1809
 
1846
 
                        ut_ad(mach_read_from_4(inode + FSEG_MAGIC_N)
1847
 
                              == FSEG_MAGIC_N_VALUE);
1848
1810
                        return(i);
1849
1811
                }
1850
1812
        }
1852
1814
        return(ULINT_UNDEFINED);
1853
1815
}
1854
1816
 
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. */
1858
1819
static
1859
1820
ulint
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
 
1824
                        if not found */
 
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 */
1866
1829
{
1867
1830
        fseg_inode_t*   inode;
1868
1831
 
1871
1834
                inode = fsp_seg_inode_page_get_nth_inode(
1872
1835
                        page, i, zip_size, mtr);
1873
1836
 
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 */
1876
1839
 
1877
1840
                        return(i);
1878
1841
                }
1879
 
 
1880
 
                ut_ad(mach_read_from_4(inode + FSEG_MAGIC_N)
1881
 
                      == FSEG_MAGIC_N_VALUE);
1882
1842
        }
1883
1843
 
1884
1844
        return(ULINT_UNDEFINED);
1885
1845
}
1886
1846
 
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. */
1890
1849
static
1891
1850
ibool
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 */
1896
1856
{
1897
1857
        fseg_inode_t*   inode;
1898
1858
        buf_block_t*    block;
1930
1890
                inode = fsp_seg_inode_page_get_nth_inode(page, i,
1931
1891
                                                         zip_size, mtr);
1932
1892
 
1933
 
                mlog_write_ull(inode + FSEG_ID, 0, mtr);
 
1893
                mlog_write_dulint(inode + FSEG_ID, ut_dulint_zero, mtr);
1934
1894
        }
1935
1895
 
1936
1896
        flst_add_last(space_header + FSP_SEG_INODES_FREE,
1938
1898
        return(TRUE);
1939
1899
}
1940
1900
 
1941
 
/**********************************************************************//**
1942
 
Allocates a new file segment inode.
1943
 
@return segment inode, or NULL if not enough space */
 
1901
/**************************************************************************
 
1902
Allocates a new file segment inode. */
1944
1903
static
1945
1904
fseg_inode_t*
1946
1905
fsp_alloc_seg_inode(
1947
1906
/*================*/
1948
 
        fsp_header_t*   space_header,   /*!< in: space header */
1949
 
        mtr_t*          mtr)            /*!< in: mini-transaction handle */
 
1907
                                        /* out: segment inode, or NULL if
 
1908
                                        not enough space */
 
1909
        fsp_header_t*   space_header,   /* in: space header */
 
1910
        mtr_t*          mtr)            /* in: mini-transaction handle */
1950
1911
{
1951
1912
        ulint           page_no;
1952
1913
        buf_block_t*    block;
1997
1958
                              page + FSEG_INODE_PAGE_NODE, mtr);
1998
1959
        }
1999
1960
 
2000
 
        ut_ad(!mach_read_from_8(inode + FSEG_ID)
2001
 
              || mach_read_from_4(inode + FSEG_MAGIC_N) == FSEG_MAGIC_N_VALUE);
2002
1961
        return(inode);
2003
1962
}
2004
1963
 
2005
 
/**********************************************************************//**
 
1964
/**************************************************************************
2006
1965
Frees a file segment inode. */
2007
1966
static
2008
1967
void
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 */
2016
1975
{
2017
1976
        page_t*         page;
2018
1977
        fsp_header_t*   space_header;
2035
1994
                              page + FSEG_INODE_PAGE_NODE, mtr);
2036
1995
        }
2037
1996
 
2038
 
        mlog_write_ull(inode + FSEG_ID, 0, mtr);
2039
 
        mlog_write_ulint(inode + FSEG_MAGIC_N, 0xfa051ce3, MLOG_4BYTES, mtr);
 
1997
        mlog_write_dulint(inode + FSEG_ID, ut_dulint_zero, mtr);
 
1998
        mlog_write_ulint(inode + FSEG_MAGIC_N, 0, MLOG_4BYTES, mtr);
2040
1999
 
2041
2000
        if (ULINT_UNDEFINED
2042
2001
            == fsp_seg_inode_page_find_used(page, zip_size, mtr)) {
2050
2009
        }
2051
2010
}
2052
2011
 
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. */
2056
2014
static
2057
2015
fseg_inode_t*
2058
 
fseg_inode_try_get(
2059
 
/*===============*/
2060
 
        fseg_header_t*  header, /*!< in: segment header */
2061
 
        ulint           space,  /*!< in: space id */
2062
 
        ulint           zip_size,/*!< in: compressed page size in bytes
 
2016
fseg_inode_get(
 
2017
/*===========*/
 
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 */
2065
2024
{
2066
2025
        fil_addr_t      inode_addr;
2067
2026
        fseg_inode_t*   inode;
2072
2031
 
2073
2032
        inode = fut_get_ptr(space, zip_size, inode_addr, RW_X_LATCH, mtr);
2074
2033
 
2075
 
        if (UNIV_UNLIKELY(!mach_read_from_8(inode + FSEG_ID))) {
2076
 
 
2077
 
                inode = NULL;
2078
 
        } else {
2079
 
                ut_ad(mach_read_from_4(inode + FSEG_MAGIC_N)
2080
 
                      == FSEG_MAGIC_N_VALUE);
2081
 
        }
2082
 
 
2083
 
        return(inode);
2084
 
}
2085
 
 
2086
 
/**********************************************************************//**
2087
 
Returns the file segment inode, page x-latched.
2088
 
@return segment inode, page x-latched */
2089
 
static
2090
 
fseg_inode_t*
2091
 
fseg_inode_get(
2092
 
/*===========*/
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 */
2098
 
{
2099
 
        fseg_inode_t*   inode
2100
 
                = fseg_inode_try_get(header, space, zip_size, mtr);
2101
 
        ut_a(inode);
2102
 
        return(inode);
2103
 
}
2104
 
 
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);
 
2035
 
 
2036
        return(inode);
 
2037
}
 
2038
 
 
2039
/**************************************************************************
 
2040
Gets the page number from the nth fragment page slot. */
2108
2041
UNIV_INLINE
2109
2042
ulint
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 */
2115
2049
{
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));
2122
2055
}
2123
2056
 
2124
 
/**********************************************************************//**
 
2057
/**************************************************************************
2125
2058
Sets the page number in the nth fragment page slot. */
2126
2059
UNIV_INLINE
2127
2060
void
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 */
2134
2067
{
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);
2139
2071
 
2140
2072
        mlog_write_ulint(inode + FSEG_FRAG_ARR + n * FSEG_FRAG_SLOT_SIZE,
2141
2073
                         page_no, MLOG_4BYTES, mtr);
2142
2074
}
2143
2075
 
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. */
2147
2078
static
2148
2079
ulint
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
 
2083
                                found */
 
2084
        fseg_inode_t*   inode,  /* in: segment inode */
 
2085
        mtr_t*          mtr)    /* in: mtr handle */
2153
2086
{
2154
2087
        ulint   i;
2155
2088
        ulint   page_no;
2168
2101
        return(ULINT_UNDEFINED);
2169
2102
}
2170
2103
 
2171
 
/**********************************************************************//**
2172
 
Finds a fragment page slot which is used and last in the array.
2173
 
@return slot index; ULINT_UNDEFINED if none found */
 
2104
/**************************************************************************
 
2105
Finds a fragment page slot which is used and last in the array. */
2174
2106
static
2175
2107
ulint
2176
2108
fseg_find_last_used_frag_page_slot(
2177
2109
/*===============================*/
2178
 
        fseg_inode_t*   inode,  /*!< in: segment inode */
2179
 
        mtr_t*          mtr)    /*!< in: mtr handle */
 
2110
                                /* out: slot index; ULINT_UNDEFINED if none
 
2111
                                found */
 
2112
        fseg_inode_t*   inode,  /* in: segment inode */
 
2113
        mtr_t*          mtr)    /* in: mtr handle */
2180
2114
{
2181
2115
        ulint   i;
2182
2116
        ulint   page_no;
2196
2130
        return(ULINT_UNDEFINED);
2197
2131
}
2198
2132
 
2199
 
/**********************************************************************//**
2200
 
Calculates reserved fragment page slots.
2201
 
@return number of fragment pages */
 
2133
/**************************************************************************
 
2134
Calculates reserved fragment page slots. */
2202
2135
static
2203
2136
ulint
2204
2137
fseg_get_n_frag_pages(
2205
2138
/*==================*/
2206
 
        fseg_inode_t*   inode,  /*!< in: segment inode */
2207
 
        mtr_t*          mtr)    /*!< in: mtr handle */
 
2139
                                /* out: number of fragment pages */
 
2140
        fseg_inode_t*   inode,  /* in: segment inode */
 
2141
        mtr_t*          mtr)    /* in: mtr handle */
2208
2142
{
2209
2143
        ulint   i;
2210
2144
        ulint   count   = 0;
2220
2154
        return(count);
2221
2155
}
2222
2156
 
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. */
2227
2159
UNIV_INTERN
2228
2160
buf_block_t*
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
2237
2172
                        on the page */
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
2243
2178
                        operation */
2244
 
        mtr_t*  mtr)    /*!< in: mtr */
 
2179
        mtr_t*  mtr)    /* in: mtr */
2245
2180
{
2246
2181
        ulint           flags;
2247
2182
        ulint           zip_size;
2248
2183
        fsp_header_t*   space_header;
2249
2184
        fseg_inode_t*   inode;
2250
 
        ib_id_t         seg_id;
 
2185
        dulint          seg_id;
2251
2186
        buf_block_t*    block   = 0; /* remove warning */
2252
2187
        fseg_header_t*  header  = 0; /* remove warning */
2253
2188
        rw_lock_t*      latch;
2276
2211
                /* This thread did not own the latch before this call: free
2277
2212
                excess pages from the insert buffer free list */
2278
2213
 
2279
 
                if (space == IBUF_SPACE_ID) {
2280
 
                        ibuf_free_excess_pages();
 
2214
                if (space == 0) {
 
2215
                        ibuf_free_excess_pages(0);
2281
2216
                }
2282
2217
        }
2283
2218
 
2301
2236
        /* Read the next segment id from space header and increment the
2302
2237
        value in space header */
2303
2238
 
2304
 
        seg_id = mach_read_from_8(space_header + FSP_SEG_ID);
2305
 
 
2306
 
        mlog_write_ull(space_header + FSP_SEG_ID, seg_id + 1, mtr);
2307
 
 
2308
 
        mlog_write_ull(inode + FSEG_ID, seg_id, mtr);
 
2239
        seg_id = mtr_read_dulint(space_header + FSP_SEG_ID, mtr);
 
2240
 
 
2241
        mlog_write_dulint(space_header + FSP_SEG_ID, ut_dulint_add(seg_id, 1),
 
2242
                          mtr);
 
2243
 
 
2244
        mlog_write_dulint(inode + FSEG_ID, seg_id, mtr);
2309
2245
        mlog_write_ulint(inode + FSEG_NOT_FULL_N_USED, 0, MLOG_4BYTES, mtr);
2310
2246
 
2311
2247
        flst_init(inode + FSEG_FREE, mtr);
2353
2289
        return(block);
2354
2290
}
2355
2291
 
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. */
2360
2294
UNIV_INTERN
2361
2295
buf_block_t*
2362
2296
fseg_create(
2363
2297
/*========*/
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
2370
2307
                        on the page */
2371
 
        mtr_t*  mtr)    /*!< in: mtr */
 
2308
        mtr_t*  mtr)    /* in: mtr */
2372
2309
{
2373
2310
        return(fseg_create_general(space, page, byte_offset, FALSE, mtr));
2374
2311
}
2375
2312
 
2376
 
/**********************************************************************//**
 
2313
/**************************************************************************
2377
2314
Calculates the number of pages reserved by a segment, and how many pages are
2378
 
currently used.
2379
 
@return number of reserved pages */
 
2315
currently used. */
2380
2316
static
2381
2317
ulint
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 */
2388
2324
{
2389
2325
        ulint   ret;
2390
2326
 
2403
2339
        return(ret);
2404
2340
}
2405
2341
 
2406
 
/**********************************************************************//**
 
2342
/**************************************************************************
2407
2343
Calculates the number of pages reserved by a segment, and how many pages are
2408
 
currently used.
2409
 
@return number of reserved pages */
 
2344
currently used. */
2410
2345
UNIV_INTERN
2411
2346
ulint
2412
2347
fseg_n_reserved_pages(
2413
2348
/*==================*/
2414
 
        fseg_header_t*  header, /*!< in: segment header */
2415
 
        ulint*          used,   /*!< out: number of pages used (<= reserved) */
2416
 
        mtr_t*          mtr)    /*!< in: mtr handle */
 
2349
                                /* out: number of reserved pages */
 
2350
        fseg_header_t*  header, /* in: segment header */
 
2351
        ulint*          used,   /* out: number of pages used (<= reserved) */
 
2352
        mtr_t*          mtr)    /* in: mtr handle */
2417
2353
{
2418
2354
        ulint           ret;
2419
2355
        fseg_inode_t*   inode;
2438
2374
        return(ret);
2439
2375
}
2440
2376
 
2441
 
/*********************************************************************//**
 
2377
/*************************************************************************
2442
2378
Tries to fill the free list of a segment with consecutive free extents.
2443
2379
This happens if the segment is big enough to allow extents in the free list,
2444
2380
the free list is empty, and the extents can be allocated consecutively from
2447
2383
void
2448
2384
fseg_fill_free_list(
2449
2385
/*================*/
2450
 
        fseg_inode_t*   inode,  /*!< in: segment inode */
2451
 
        ulint           space,  /*!< in: space id */
2452
 
        ulint           zip_size,/*!< in: compressed page size in bytes
 
2386
        fseg_inode_t*   inode,  /* in: segment inode */
 
2387
        ulint           space,  /* in: space id */
 
2388
        ulint           zip_size,/* in: compressed page size in bytes
2453
2389
                                or 0 for uncompressed pages */
2454
 
        ulint           hint,   /*!< in: hint which extent would be good as
 
2390
        ulint           hint,   /* in: hint which extent would be good as
2455
2391
                                the first extent */
2456
 
        mtr_t*          mtr)    /*!< in: mtr */
 
2392
        mtr_t*          mtr)    /* in: mtr */
2457
2393
{
2458
2394
        xdes_t* descr;
2459
2395
        ulint   i;
2460
 
        ib_id_t seg_id;
 
2396
        dulint  seg_id;
2461
2397
        ulint   reserved;
2462
2398
        ulint   used;
2463
2399
 
2494
2430
 
2495
2431
                xdes_set_state(descr, XDES_FSEG, mtr);
2496
2432
 
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);
2501
2435
 
2502
2436
                flst_add_last(inode + FSEG_FREE, descr + XDES_FLST_NODE, mtr);
2503
2437
                hint += FSP_EXTENT_SIZE;
2504
2438
        }
2505
2439
}
2506
2440
 
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! */
2513
2445
static
2514
2446
xdes_t*
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
 
2451
                                not be allocated */
 
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 */
2522
2457
{
2523
2458
        xdes_t*         descr;
2524
 
        ib_id_t         seg_id;
 
2459
        dulint          seg_id;
2525
2460
        fil_addr_t      first;
2526
2461
 
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);
2529
2463
 
2530
2464
        if (flst_get_len(inode + FSEG_FREE, mtr) > 0) {
2531
2465
                /* Segment free list is not empty, allocate from it */
2542
2476
                        return(NULL);
2543
2477
                }
2544
2478
 
2545
 
                seg_id = mach_read_from_8(inode + FSEG_ID);
 
2479
                seg_id = mtr_read_dulint(inode + FSEG_ID, mtr);
2546
2480
 
2547
2481
                xdes_set_state(descr, XDES_FSEG, mtr);
2548
 
                mlog_write_ull(descr + XDES_ID, seg_id, mtr);
 
2482
                mlog_write_dulint(descr + XDES_ID, seg_id, mtr);
2549
2483
                flst_add_last(inode + FSEG_FREE, descr + XDES_FLST_NODE, mtr);
2550
2484
 
2551
2485
                /* Try to fill the segment free list */
2557
2491
        return(descr);
2558
2492
}
2559
2493
 
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
2563
 
fragmentation.
2564
 
@return the allocated page number, FIL_NULL if no page could be allocated */
 
2497
fragmentation. */
2565
2498
static
2566
2499
ulint
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 */
2580
2515
{
2581
2516
        fsp_header_t*   space_header;
2582
2517
        ulint           space_size;
2583
 
        ib_id_t         seg_id;
 
2518
        dulint          seg_id;
2584
2519
        ulint           used;
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;
2591
2526
        ibool           success;
2592
2527
        ulint           n;
2596
2531
        ut_ad(mach_read_from_4(seg_inode + FSEG_MAGIC_N)
2597
2532
              == FSEG_MAGIC_N_VALUE);
2598
2533
        ut_ad(!((page_offset(seg_inode) - FSEG_ARR_OFFSET) % FSEG_INODE_SIZE));
2599
 
        seg_id = mach_read_from_8(seg_inode + FSEG_ID);
 
2534
        seg_id = mtr_read_dulint(seg_inode + FSEG_ID, mtr);
2600
2535
 
2601
 
        ut_ad(seg_id);
 
2536
        ut_ad(!ut_dulint_is_zero(seg_id));
2602
2537
 
2603
2538
        reserved = fseg_n_reserved_pages_low(seg_inode, &used, mtr);
2604
2539
 
2616
2551
        /* In the big if-else below we look for ret_page and ret_descr */
2617
2552
        /*-------------------------------------------------------------*/
2618
2553
        if ((xdes_get_state(descr, mtr) == XDES_FSEG)
2619
 
            && mach_read_from_8(descr + XDES_ID) == seg_id
 
2554
            && (0 == ut_dulint_cmp(mtr_read_dulint(descr + XDES_ID,
 
2555
                                                   mtr), seg_id))
2620
2556
            && (xdes_get_bit(descr, XDES_FREE_BIT,
2621
2557
                             hint % FSP_EXTENT_SIZE, mtr) == TRUE)) {
2622
2558
 
2638
2574
                ut_a(ret_descr == descr);
2639
2575
 
2640
2576
                xdes_set_state(ret_descr, XDES_FSEG, mtr);
2641
 
                mlog_write_ull(ret_descr + XDES_ID, seg_id, mtr);
 
2577
                mlog_write_dulint(ret_descr + XDES_ID, seg_id, mtr);
2642
2578
                flst_add_last(seg_inode + FSEG_FREE,
2643
2579
                              ret_descr + XDES_FLST_NODE, mtr);
2644
2580
 
2667
2603
                }
2668
2604
                /*-----------------------------------------------------------*/
2669
2605
        } else if ((xdes_get_state(descr, mtr) == XDES_FSEG)
2670
 
                   && mach_read_from_8(descr + XDES_ID) == seg_id
 
2606
                   && (0 == ut_dulint_cmp(mtr_read_dulint(descr + XDES_ID,
 
2607
                                                          mtr), seg_id))
2671
2608
                   && (!xdes_is_full(descr, mtr))) {
2672
2609
 
2673
2610
                /* 4. We can take the page from the same extent as the
2803
2740
        return(ret_page);
2804
2741
}
2805
2742
 
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
2809
 
fragmentation.
2810
 
@return allocated page offset, FIL_NULL if no page could be allocated */
 
2746
fragmentation. */
2811
2747
UNIV_INTERN
2812
2748
ulint
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
2826
2764
                                page */
2827
 
        mtr_t*          mtr)    /*!< in: mtr handle */
 
2765
        mtr_t*          mtr)    /* in: mtr handle */
2828
2766
{
2829
2767
        fseg_inode_t*   inode;
2830
2768
        ulint           space;
2850
2788
                /* This thread did not own the latch before this call: free
2851
2789
                excess pages from the insert buffer free list */
2852
2790
 
2853
 
                if (space == IBUF_SPACE_ID) {
2854
 
                        ibuf_free_excess_pages();
 
2791
                if (space == 0) {
 
2792
                        ibuf_free_excess_pages(0);
2855
2793
                }
2856
2794
        }
2857
2795
 
2874
2812
        return(page_no);
2875
2813
}
2876
2814
 
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
2880
 
fragmentation.
2881
 
@return allocated page offset, FIL_NULL if no page could be allocated */
 
2818
fragmentation. */
2882
2819
UNIV_INTERN
2883
2820
ulint
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 */
2894
2833
{
2895
2834
        return(fseg_alloc_free_page_general(seg_header, hint, direction,
2896
2835
                                            FALSE, mtr));
2897
2836
}
2898
2837
 
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
2904
 
pages.
2905
 
@return TRUE if there were >= 3 free pages, or we were able to extend */
 
2843
pages. */
2906
2844
static
2907
2845
ibool
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,
2912
2852
                                        x-latched */
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 */
2916
2856
{
2917
2857
        xdes_t* descr;
2918
2858
        ulint   n_used;
2935
2875
                                                   space_header, mtr));
2936
2876
}
2937
2877
 
2938
 
/**********************************************************************//**
 
2878
/**************************************************************************
2939
2879
Reserves free pages from a tablespace. All mini-transactions which may
2940
2880
use several pages from the tablespace should call this function beforehand
2941
2881
and reserve enough free extents so that they certainly will be able
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. */
2964
2903
UNIV_INTERN
2965
2904
ibool
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 */
2975
2915
{
2976
2916
        fsp_header_t*   space_header;
2977
2917
        rw_lock_t*      latch;
3071
3011
        return(FALSE);
3072
3012
}
3073
3013
 
3074
 
/**********************************************************************//**
 
3014
/**************************************************************************
3075
3015
This function should be used to get information on how much we still
3076
3016
will be able to insert new data to the database without running out the
3077
3017
tablespace. Only free extents are taken into account and we also subtract
3078
 
the safety margin required by the above function fsp_reserve_free_extents.
3079
 
@return available space in kB */
 
3018
the safety margin required by the above function fsp_reserve_free_extents. */
3080
3019
UNIV_INTERN
3081
3020
ullint
3082
3021
fsp_get_available_space_in_free_extents(
3083
3022
/*====================================*/
3084
 
        ulint   space)  /*!< in: space id */
 
3023
                        /* out: available space in kB */
 
3024
        ulint   space)  /* in: space id */
3085
3025
{
3086
3026
        fsp_header_t*   space_header;
3087
3027
        ulint           n_free_list_ext;
3162
3102
        }
3163
3103
}
3164
3104
 
3165
 
/********************************************************************//**
 
3105
/************************************************************************
3166
3106
Marks a page used. The page must reside within the extents of the given
3167
3107
segment. */
3168
3108
static
3169
3109
void
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 */
3178
3118
{
3179
3119
        xdes_t* descr;
3180
3120
        ulint   not_full_n_used;
3181
3121
 
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);
3186
3124
 
3187
3125
        descr = xdes_get_descriptor(space, zip_size, page, mtr);
3188
3126
 
3222
3160
        }
3223
3161
}
3224
3162
 
3225
 
/**********************************************************************//**
 
3163
/**************************************************************************
3226
3164
Frees a single page of a segment. */
3227
3165
static
3228
3166
void
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 */
3237
3175
{
3238
3176
        xdes_t* descr;
3239
3177
        ulint   not_full_n_used;
3240
3178
        ulint   state;
3241
 
        ib_id_t descr_id;
3242
 
        ib_id_t seg_id;
 
3179
        dulint  descr_id;
 
3180
        dulint  seg_id;
3243
3181
        ulint   i;
3244
3182
 
3245
3183
        ut_ad(seg_inode && mtr);
3271
3209
                        "InnoDB: database!\n", (ulong) page);
3272
3210
crash:
3273
3211
                fputs("InnoDB: Please refer to\n"
3274
 
                      "InnoDB: " REFMAN "forcing-recovery.html\n"
 
3212
                      "InnoDB: http://dev.mysql.com/doc/refman/5.1/en/"
 
3213
                      "forcing-recovery.html\n"
3275
3214
                      "InnoDB: about forcing recovery.\n", stderr);
3276
3215
                ut_error;
3277
3216
        }
3298
3237
 
3299
3238
        /* If we get here, the page is in some extent of the segment */
3300
3239
 
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);
3303
3242
#if 0
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,
3309
 
                (ullint) descr_id,
3310
 
                (ullint) seg_id);
 
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));
3311
3252
#endif /* 0 */
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: ",
3314
3255
                      stderr);
3315
3256
                ut_print_buf(stderr, descr, 40);
3321
3262
                        "InnoDB: Serious error: InnoDB is trying to"
3322
3263
                        " free space %lu page %lu,\n"
3323
3264
                        "InnoDB: which does not belong to"
3324
 
                        " segment %llu but belongs\n"
3325
 
                        "InnoDB: to segment %llu.\n",
 
3265
                        " segment %lu %lu but belongs\n"
 
3266
                        "InnoDB: to segment %lu %lu.\n",
3326
3267
                        (ulong) space, (ulong) page,
3327
 
                        (ullint) descr_id,
3328
 
                        (ullint) seg_id);
 
3268
                        (ulong) ut_dulint_get_high(descr_id),
 
3269
                        (ulong) ut_dulint_get_low(descr_id),
 
3270
                        (ulong) ut_dulint_get_high(seg_id),
 
3271
                        (ulong) ut_dulint_get_low(seg_id));
3329
3272
                goto crash;
3330
3273
        }
3331
3274
 
3357
3300
        }
3358
3301
}
3359
3302
 
3360
 
/**********************************************************************//**
 
3303
/**************************************************************************
3361
3304
Frees a single page of a segment. */
3362
3305
UNIV_INTERN
3363
3306
void
3364
3307
fseg_free_page(
3365
3308
/*===========*/
3366
 
        fseg_header_t*  seg_header, /*!< in: segment header */
3367
 
        ulint           space,  /*!< in: space id */
3368
 
        ulint           page,   /*!< in: page offset */
3369
 
        mtr_t*          mtr)    /*!< in: mtr handle */
 
3309
        fseg_header_t*  seg_header, /* in: segment header */
 
3310
        ulint           space,  /* in: space id */
 
3311
        ulint           page,   /* in: page offset */
 
3312
        mtr_t*          mtr)    /* in: mtr handle */
3370
3313
{
3371
3314
        ulint           flags;
3372
3315
        ulint           zip_size;
3390
3333
#endif
3391
3334
}
3392
3335
 
3393
 
/**********************************************************************//**
 
3336
/**************************************************************************
3394
3337
Frees an extent of a segment to the space free list. */
3395
3338
static
3396
3339
void
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 */
3405
3348
{
3406
3349
        ulint   first_page_in_extent;
3407
3350
        xdes_t* descr;
3414
3357
        descr = xdes_get_descriptor(space, zip_size, page, mtr);
3415
3358
 
3416
3359
        ut_a(xdes_get_state(descr, mtr) == XDES_FSEG);
3417
 
        ut_a(!memcmp(descr + XDES_ID, seg_inode + FSEG_ID, 8));
3418
 
        ut_ad(mach_read_from_4(seg_inode + FSEG_MAGIC_N)
3419
 
              == FSEG_MAGIC_N_VALUE);
 
3360
        ut_a(0 == ut_dulint_cmp(mtr_read_dulint(descr + XDES_ID, mtr),
 
3361
                                mtr_read_dulint(seg_inode + FSEG_ID, mtr)));
3420
3362
 
3421
3363
        first_page_in_extent = page - (page % FSP_EXTENT_SIZE);
3422
3364
 
3462
3404
#endif
3463
3405
}
3464
3406
 
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
3469
 
mini-transaction.
3470
 
@return TRUE if freeing completed */
 
3411
mini-transaction. */
3471
3412
UNIV_INTERN
3472
3413
ibool
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 */
3480
3422
{
3481
3423
        ulint           n;
3482
3424
        ulint           page;
3507
3449
        ut_a(descr);
3508
3450
        ut_a(xdes_get_bit(descr, XDES_FREE_BIT,
3509
3451
                          header_page % FSP_EXTENT_SIZE, mtr) == FALSE);
3510
 
        inode = fseg_inode_try_get(header, space, zip_size, mtr);
3511
 
 
3512
 
        if (UNIV_UNLIKELY(inode == NULL)) {
3513
 
                fprintf(stderr, "double free of inode from %u:%u\n",
3514
 
                        (unsigned) space, (unsigned) header_page);
3515
 
                return(TRUE);
3516
 
        }
 
3452
        inode = fseg_inode_get(header, space, zip_size, mtr);
3517
3453
 
3518
3454
        descr = fseg_get_first_extent(inode, space, zip_size, mtr);
3519
3455
 
3551
3487
        return(FALSE);
3552
3488
}
3553
3489
 
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. */
3558
3493
UNIV_INTERN
3559
3494
ibool
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
 
3498
                                header page */
 
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 */
3565
3502
{
3566
3503
        ulint           n;
3567
3504
        ulint           page;
3616
3553
        return(FALSE);
3617
3554
}
3618
3555
 
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. */
 
3559
UNIV_INTERN
 
3560
void
 
3561
fseg_free(
 
3562
/*======*/
 
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
 
3567
                        placed */
 
3568
        ulint   offset) /* in: byte offset of the segment header on that
 
3569
                        page */
 
3570
{
 
3571
        mtr_t           mtr;
 
3572
        ibool           finished;
 
3573
        fseg_header_t*  header;
 
3574
        fil_addr_t      addr;
 
3575
 
 
3576
        addr.page = page_no;
 
3577
        addr.boffset = offset;
 
3578
 
 
3579
        for (;;) {
 
3580
                mtr_start(&mtr);
 
3581
 
 
3582
                header = fut_get_ptr(space, zip_size, addr, RW_X_LATCH, &mtr);
 
3583
 
 
3584
                finished = fseg_free_step(header, &mtr);
 
3585
 
 
3586
                mtr_commit(&mtr);
 
3587
 
 
3588
                if (finished) {
 
3589
 
 
3590
                        return;
 
3591
                }
 
3592
        }
 
3593
}
 
3594
 
 
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
3622
 
-> FSEG_FREE.
3623
 
@return the first extent descriptor, or NULL if none */
 
3598
-> FSEG_FREE. */
3624
3599
static
3625
3600
xdes_t*
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
 
3604
                                none */
 
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 */
3633
3610
{
3634
3611
        fil_addr_t      first;
3635
3612
        xdes_t*         descr;
3637
3614
        ut_ad(inode && mtr);
3638
3615
 
3639
3616
        ut_ad(space == page_get_space_id(page_align(inode)));
3640
 
        ut_ad(mach_read_from_4(inode + FSEG_MAGIC_N) == FSEG_MAGIC_N_VALUE);
3641
3617
 
3642
3618
        first = fil_addr_null;
3643
3619
 
3663
3639
        return(descr);
3664
3640
}
3665
3641
 
3666
 
/*******************************************************************//**
3667
 
Validates a segment.
3668
 
@return TRUE if ok */
 
3642
/***********************************************************************
 
3643
Validates a segment. */
3669
3644
static
3670
3645
ibool
3671
3646
fseg_validate_low(
3672
3647
/*==============*/
3673
 
        fseg_inode_t*   inode, /*!< in: segment inode */
3674
 
        mtr_t*          mtr2)   /*!< in: mtr */
 
3648
                                /* out: TRUE if ok */
 
3649
        fseg_inode_t*   inode, /* in: segment inode */
 
3650
        mtr_t*          mtr2)   /* in: mtr */
3675
3651
{
3676
3652
        ulint           space;
3677
 
        ib_id_t         seg_id;
 
3653
        dulint          seg_id;
3678
3654
        mtr_t           mtr;
3679
3655
        xdes_t*         descr;
3680
3656
        fil_addr_t      node_addr;
3686
3662
 
3687
3663
        space = page_get_space_id(page_align(inode));
3688
3664
 
3689
 
        seg_id = mach_read_from_8(inode + FSEG_ID);
 
3665
        seg_id = mtr_read_dulint(inode + FSEG_ID, mtr2);
3690
3666
        n_used = mtr_read_ulint(inode + FSEG_NOT_FULL_N_USED,
3691
3667
                                MLOG_4BYTES, mtr2);
3692
3668
        flst_validate(inode + FSEG_FREE, mtr2);
3709
3685
 
3710
3686
                ut_a(xdes_get_n_used(descr, &mtr) == 0);
3711
3687
                ut_a(xdes_get_state(descr, &mtr) == XDES_FSEG);
3712
 
                ut_a(mach_read_from_8(descr + XDES_ID) == seg_id);
 
3688
                ut_a(!ut_dulint_cmp(mtr_read_dulint(descr + XDES_ID, &mtr),
 
3689
                                    seg_id));
3713
3690
 
3714
3691
                node_addr = flst_get_next_addr(descr + XDES_FLST_NODE, &mtr);
3715
3692
                mtr_commit(&mtr);
3733
3710
                ut_a(xdes_get_n_used(descr, &mtr) > 0);
3734
3711
                ut_a(xdes_get_n_used(descr, &mtr) < FSP_EXTENT_SIZE);
3735
3712
                ut_a(xdes_get_state(descr, &mtr) == XDES_FSEG);
3736
 
                ut_a(mach_read_from_8(descr + XDES_ID) == seg_id);
 
3713
                ut_a(!ut_dulint_cmp(mtr_read_dulint(descr + XDES_ID, &mtr),
 
3714
                                    seg_id));
3737
3715
 
3738
3716
                n_used2 += xdes_get_n_used(descr, &mtr);
3739
3717
 
3758
3736
 
3759
3737
                ut_a(xdes_get_n_used(descr, &mtr) == FSP_EXTENT_SIZE);
3760
3738
                ut_a(xdes_get_state(descr, &mtr) == XDES_FSEG);
3761
 
                ut_a(mach_read_from_8(descr + XDES_ID) == seg_id);
 
3739
                ut_a(!ut_dulint_cmp(mtr_read_dulint(descr + XDES_ID, &mtr),
 
3740
                                    seg_id));
3762
3741
 
3763
3742
                node_addr = flst_get_next_addr(descr + XDES_FLST_NODE, &mtr);
3764
3743
                mtr_commit(&mtr);
3769
3748
        return(TRUE);
3770
3749
}
3771
3750
 
3772
 
#ifdef UNIV_DEBUG
3773
 
/*******************************************************************//**
3774
 
Validates a segment.
3775
 
@return TRUE if ok */
 
3751
/***********************************************************************
 
3752
Validates a segment. */
3776
3753
UNIV_INTERN
3777
3754
ibool
3778
3755
fseg_validate(
3779
3756
/*==========*/
3780
 
        fseg_header_t*  header, /*!< in: segment header */
3781
 
        mtr_t*          mtr)    /*!< in: mtr */
 
3757
                                /* out: TRUE if ok */
 
3758
        fseg_header_t*  header, /* in: segment header */
 
3759
        mtr_t*          mtr)    /* in: mtr */
3782
3760
{
3783
3761
        fseg_inode_t*   inode;
3784
3762
        ibool           ret;
3797
3775
 
3798
3776
        return(ret);
3799
3777
}
3800
 
#endif /* UNIV_DEBUG */
3801
3778
 
3802
 
/*******************************************************************//**
 
3779
/***********************************************************************
3803
3780
Writes info of a segment. */
3804
3781
static
3805
3782
void
3806
3783
fseg_print_low(
3807
3784
/*===========*/
3808
 
        fseg_inode_t*   inode, /*!< in: segment inode */
3809
 
        mtr_t*          mtr)    /*!< in: mtr */
 
3785
        fseg_inode_t*   inode, /* in: segment inode */
 
3786
        mtr_t*          mtr)    /* in: mtr */
3810
3787
{
3811
3788
        ulint   space;
 
3789
        ulint   seg_id_low;
 
3790
        ulint   seg_id_high;
3812
3791
        ulint   n_used;
3813
3792
        ulint   n_frag;
3814
3793
        ulint   n_free;
3817
3796
        ulint   reserved;
3818
3797
        ulint   used;
3819
3798
        ulint   page_no;
3820
 
        ib_id_t seg_id;
 
3799
        dulint   d_var;
3821
3800
 
3822
3801
        ut_ad(mtr_memo_contains_page(mtr, inode, MTR_MEMO_PAGE_X_FIX));
3823
3802
        space = page_get_space_id(page_align(inode));
3825
3804
 
3826
3805
        reserved = fseg_n_reserved_pages_low(inode, &used, mtr);
3827
3806
 
3828
 
        seg_id = mach_read_from_8(inode + FSEG_ID);
 
3807
        d_var = mtr_read_dulint(inode + FSEG_ID, mtr);
 
3808
 
 
3809
        seg_id_low = ut_dulint_get_low(d_var);
 
3810
        seg_id_high = ut_dulint_get_high(d_var);
3829
3811
 
3830
3812
        n_used = mtr_read_ulint(inode + FSEG_NOT_FULL_N_USED,
3831
3813
                                MLOG_4BYTES, mtr);
3835
3817
        n_full = flst_get_len(inode + FSEG_FULL, mtr);
3836
3818
 
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",
3842
 
                (ullint) seg_id,
 
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);
3848
3829
}
3849
3830
 
3850
3831
#ifdef UNIV_BTR_PRINT
3851
 
/*******************************************************************//**
 
3832
/***********************************************************************
3852
3833
Writes info of a segment. */
3853
3834
UNIV_INTERN
3854
3835
void
3855
3836
fseg_print(
3856
3837
/*=======*/
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 */
3859
3840
{
3860
3841
        fseg_inode_t*   inode;
3861
3842
        ulint           space;
3873
3854
}
3874
3855
#endif /* UNIV_BTR_PRINT */
3875
3856
 
3876
 
/*******************************************************************//**
3877
 
Validates the file space system and its segments.
3878
 
@return TRUE if ok */
 
3857
/***********************************************************************
 
3858
Validates the file space system and its segments. */
3879
3859
UNIV_INTERN
3880
3860
ibool
3881
3861
fsp_validate(
3882
3862
/*=========*/
3883
 
        ulint   space)  /*!< in: space id */
 
3863
                        /* out: TRUE if ok */
 
3864
        ulint   space)  /* in: space id */
3884
3865
{
3885
3866
        fsp_header_t*   header;
3886
3867
        fseg_inode_t*   seg_inode;
4041
4022
 
4042
4023
                        seg_inode = fsp_seg_inode_page_get_nth_inode(
4043
4024
                                seg_inode_page, n, zip_size, &mtr);
4044
 
                        ut_a(mach_read_from_8(seg_inode + FSEG_ID) != 0);
 
4025
                        ut_a(!ut_dulint_is_zero(
 
4026
                                     mach_read_from_8(seg_inode + FSEG_ID)));
4045
4027
                        fseg_validate_low(seg_inode, &mtr);
4046
4028
 
4047
4029
                        descr_count += flst_get_len(seg_inode + FSEG_FREE,
4086
4068
 
4087
4069
                        seg_inode = fsp_seg_inode_page_get_nth_inode(
4088
4070
                                seg_inode_page, n, zip_size, &mtr);
4089
 
                        if (mach_read_from_8(seg_inode + FSEG_ID)) {
 
4071
                        if (!ut_dulint_is_zero(
 
4072
                                    mach_read_from_8(seg_inode + FSEG_ID))) {
4090
4073
                                fseg_validate_low(seg_inode, &mtr);
4091
4074
 
4092
4075
                                descr_count += flst_get_len(
4126
4109
        return(TRUE);
4127
4110
}
4128
4111
 
4129
 
/*******************************************************************//**
 
4112
/***********************************************************************
4130
4113
Prints info of a file space. */
4131
4114
UNIV_INTERN
4132
4115
void
4133
4116
fsp_print(
4134
4117
/*======*/
4135
 
        ulint   space)  /*!< in: space id */
 
4118
        ulint   space)  /* in: space id */
4136
4119
{
4137
4120
        fsp_header_t*   header;
4138
4121
        fseg_inode_t*   seg_inode;
4148
4131
        ulint           n_free;
4149
4132
        ulint           n_free_frag;
4150
4133
        ulint           n_full_frag;
4151
 
        ib_id_t         seg_id;
 
4134
        ulint           seg_id_low;
 
4135
        ulint           seg_id_high;
4152
4136
        ulint           n;
4153
4137
        ulint           n_segs          = 0;
 
4138
        dulint          d_var;
4154
4139
        mtr_t           mtr;
4155
4140
        mtr_t           mtr2;
4156
4141
 
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);
4182
4167
 
4183
 
        seg_id = mach_read_from_8(header + FSP_SEG_ID);
 
4168
        d_var = mtr_read_dulint(header + FSP_SEG_ID, &mtr);
 
4169
 
 
4170
        seg_id_low = ut_dulint_get_low(d_var);
 
4171
        seg_id_high = ut_dulint_get_high(d_var);
4184
4172
 
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",
4191
4179
                (ulong) space,
4192
4180
                (ulong) size, (ulong) free_limit, (ulong) n_free,
4193
4181
                (ulong) n_free_frag, (ulong) frag_n_used, (ulong) n_full_frag,
4194
 
                (ullint) seg_id);
 
4182
                (ulong) seg_id_high, (ulong) seg_id_low);
4195
4183
 
4196
4184
        mtr_commit(&mtr);
4197
4185
 
4221
4209
 
4222
4210
                        seg_inode = fsp_seg_inode_page_get_nth_inode(
4223
4211
                                seg_inode_page, n, zip_size, &mtr);
4224
 
                        ut_a(mach_read_from_8(seg_inode + FSEG_ID) != 0);
 
4212
                        ut_a(!ut_dulint_is_zero(
 
4213
                                     mach_read_from_8(seg_inode + FSEG_ID)));
4225
4214
                        fseg_print_low(seg_inode, &mtr);
4226
4215
 
4227
4216
                        n_segs++;
4258
4247
 
4259
4248
                        seg_inode = fsp_seg_inode_page_get_nth_inode(
4260
4249
                                seg_inode_page, n, zip_size, &mtr);
4261
 
                        if (mach_read_from_8(seg_inode + FSEG_ID)) {
 
4250
                        if (!ut_dulint_is_zero(
 
4251
                                    mach_read_from_8(seg_inode + FSEG_ID))) {
4262
4252
 
4263
4253
                                fseg_print_low(seg_inode, &mtr);
4264
4254
                                n_segs++;
4276
4266
 
4277
4267
        fprintf(stderr, "NUMBER of file segments: %lu\n", (ulong) n_segs);
4278
4268
}
4279
 
#endif /* !UNIV_HOTBACKUP */