1578
1578
const dict_index_t* index, /*!< in: index being created */
1579
1579
merge_file_t* file, /*!< in/out: file containing
1580
1580
index entries */
1581
ulint* half, /*!< in/out: half the file */
1582
1581
row_merge_block_t* block, /*!< in/out: 3 buffers */
1583
1582
int* tmpfd, /*!< in/out: temporary file handle */
1584
TABLE* table) /*!< in/out: MySQL table, for
1583
TABLE* table, /*!< in/out: MySQL table, for
1585
1584
reporting erroneous key value
1586
1585
if applicable */
1586
ulint* num_run,/*!< in/out: Number of runs remain
1588
ulint* run_offset) /*!< in/out: Array contains the
1589
first offset number for each merge
1588
1592
ulint foffs0; /*!< first input offset */
1589
1593
ulint foffs1; /*!< second input offset */
1590
1594
ulint error; /*!< error code */
1591
1595
merge_file_t of; /*!< output file */
1592
const ulint ihalf = *half;
1596
const ulint ihalf = run_offset[*num_run / 2];
1593
1597
/*!< half the input file */
1594
ulint ohalf; /*!< half the output file */
1599
/*!< num of runs generated from this merge */
1596
1601
UNIV_MEM_ASSERT_W(block[0], 3 * sizeof block[0]);
1597
1603
ut_ad(ihalf < file->offset);
1599
1605
of.fd = *tmpfd;
1603
1609
/* Merge blocks to the output file. */
1606
1611
foffs1 = ihalf;
1613
UNIV_MEM_INVALID(run_offset, *num_run * sizeof *run_offset);
1608
1615
for (; foffs0 < ihalf && foffs1 < file->offset; foffs0++, foffs1++) {
1609
ulint ahalf; /*!< arithmetic half the input file */
1611
1617
if (UNIV_UNLIKELY(trx_is_interrupted(trx))) {
1612
1618
return(DB_INTERRUPTED);
1621
/* Remember the offset number for this run */
1622
run_offset[n_run++] = of.offset;
1615
1624
error = row_merge_blocks(index, file, block,
1616
1625
&foffs0, &foffs1, &of, table);
1622
/* Record the offset of the output file when
1623
approximately half the output has been generated. In
1624
this way, the next invocation of row_merge() will
1625
spend most of the time in this loop. The initial
1626
estimate is ohalf==0. */
1627
ahalf = file->offset / 2;
1628
ut_ad(ohalf <= of.offset);
1630
/* Improve the estimate until reaching half the input
1631
file size, or we can not get any closer to it. All
1632
comparands should be non-negative when !(ohalf < ahalf)
1633
because ohalf <= of.offset. */
1634
if (ohalf < ahalf || of.offset - ahalf < ohalf - ahalf) {
1639
1633
/* Copy the last blocks, if there are any. */
1643
1637
return(DB_INTERRUPTED);
1640
/* Remember the offset number for this run */
1641
run_offset[n_run++] = of.offset;
1646
1643
if (!row_merge_blocks_copy(index, file, block, &foffs0, &of)) {
1647
1644
return(DB_CORRUPTION);
1655
1652
return(DB_INTERRUPTED);
1655
/* Remember the offset number for this run */
1656
run_offset[n_run++] = of.offset;
1658
1658
if (!row_merge_blocks_copy(index, file, block, &foffs1, &of)) {
1659
1659
return(DB_CORRUPTION);
1666
1666
return(DB_CORRUPTION);
1669
ut_ad(n_run <= *num_run);
1673
/* Each run can contain one or more offsets. As merge goes on,
1674
the number of runs (to merge) will reduce until we have one
1675
single run. So the number of runs will always be smaller than
1676
the number of offsets in file */
1677
ut_ad((*num_run) <= file->offset);
1679
/* The number of offsets in output file is always equal or
1680
smaller than input file */
1681
ut_ad(of.offset <= file->offset);
1669
1683
/* Swap file descriptors for the next pass. */
1670
1684
*tmpfd = file->fd;
1674
1687
UNIV_MEM_INVALID(block[0], 3 * sizeof block[0]);
1694
1707
if applicable */
1696
1709
ulint half = file->offset / 2;
1712
ulint error = DB_SUCCESS;
1714
/* Record the number of merge runs we need to perform */
1715
num_runs = file->offset;
1717
/* If num_runs are less than 1, nothing to merge */
1718
if (num_runs <= 1) {
1722
/* "run_offset" records each run's first offset number */
1723
run_offset = (ulint*) mem_alloc(file->offset * sizeof(ulint));
1725
/* This tells row_merge() where to start for the first round
1727
run_offset[half] = half;
1698
1729
/* The file should always contain at least one byte (the end
1699
1730
of file marker). Thus, it must be at least one block. */
1700
1731
ut_ad(file->offset > 0);
1733
/* Merge the runs until we have one big run */
1735
error = row_merge(trx, index, file, block, tmpfd,
1736
table, &num_runs, run_offset);
1705
error = row_merge(trx, index, file, &half,
1706
block, tmpfd, table);
1738
UNIV_MEM_ASSERT_RW(run_offset, num_runs * sizeof *run_offset);
1708
1740
if (error != DB_SUCCESS) {
1712
/* half > 0 should hold except when the file consists
1713
of one block. No need to merge further then. */
1714
ut_ad(half > 0 || file->offset == 1);
1715
} while (half < file->offset && half > 0);
1743
} while (num_runs > 1);
1745
mem_free(run_offset);
1720
1750
/*************************************************************//**
2315
2345
ut_a(trx->dict_operation_lock_mode == RW_X_LATCH);
2347
/* store the old/current name to an automatic variable */
2348
if (strlen(old_table->name) + 1 <= sizeof(old_name)) {
2349
memcpy(old_name, old_table->name, strlen(old_table->name) + 1);
2351
ut_print_timestamp(stderr);
2352
fprintf(stderr, "InnoDB: too long table name: '%s', "
2353
"max length is %d\n", old_table->name,
2354
MAX_TABLE_NAME_LEN);
2317
2358
trx->op_info = "renaming tables";
2319
2360
/* We use the private SQL parser of Innobase to generate the query