~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to plugin/innobase/row/row0merge.c

  • Committer: Brian Aker
  • Date: 2010-12-16 20:27:14 UTC
  • mto: (2002.1.4 clean) (2015.1.1 clean)
  • mto: This revision was merged to the branch mainline in revision 2003.
  • Revision ID: brian@tangent.org-20101216202714-fmzbmyoetoi8pr6j
First pass through, removing the need for us track the position in this
manner.

Show diffs side-by-side

added added

removed removed

Lines of Context:
339
339
                if (ifield->prefix_len) {
340
340
                        len = dtype_get_at_most_n_mbchars(
341
341
                                col->prtype,
342
 
                                col->mbminlen, col->mbmaxlen,
 
342
                                col->mbminmaxlen,
343
343
                                ifield->prefix_len,
344
344
                                len, dfield_get_data(field));
345
345
                        dfield_set_len(field, len);
1603
1603
        const dict_index_t*     index,  /*!< in: index being created */
1604
1604
        merge_file_t*           file,   /*!< in/out: file containing
1605
1605
                                        index entries */
1606
 
        ulint*                  half,   /*!< in/out: half the file */
1607
1606
        row_merge_block_t*      block,  /*!< in/out: 3 buffers */
1608
1607
        int*                    tmpfd,  /*!< in/out: temporary file handle */
1609
 
        struct TABLE*           table)  /*!< in/out: MySQL table, for
1610
 
                                        reporting erroneous key value
1611
 
                                        if applicable */
 
1608
        struct TABLE*           table,  /*!< in/out: MySQL table, for
 
1609
                                        reporting erroneous key value
 
1610
                                        if applicable */
 
1611
        ulint*                  num_run,/*!< in/out: Number of runs remain
 
1612
                                        to be merged */
 
1613
        ulint*                  run_offset) /*!< in/out: Array contains the
 
1614
                                        first offset number for each merge
 
1615
                                        run */
1612
1616
{
1613
1617
        ulint           foffs0; /*!< first input offset */
1614
1618
        ulint           foffs1; /*!< second input offset */
1615
1619
        ulint           error;  /*!< error code */
1616
1620
        merge_file_t    of;     /*!< output file */
1617
 
        const ulint     ihalf   = *half;
 
1621
        const ulint     ihalf   = run_offset[*num_run / 2];
1618
1622
                                /*!< half the input file */
1619
 
        ulint           ohalf;  /*!< half the output file */
 
1623
        ulint           n_run   = 0;
 
1624
                                /*!< num of runs generated from this merge */
 
1625
 
1620
1626
 
1621
1627
        UNIV_MEM_ASSERT_W(block[0], 3 * sizeof block[0]);
1622
1628
        ut_ad(ihalf < file->offset);
1634
1640
#endif /* POSIX_FADV_SEQUENTIAL */
1635
1641
 
1636
1642
        /* Merge blocks to the output file. */
1637
 
        ohalf = 0;
1638
1643
        foffs0 = 0;
1639
1644
        foffs1 = ihalf;
1640
1645
 
 
1646
        UNIV_MEM_INVALID(run_offset, *num_run * sizeof *run_offset);
 
1647
 
1641
1648
        for (; foffs0 < ihalf && foffs1 < file->offset; foffs0++, foffs1++) {
1642
 
                ulint   ahalf;  /*!< arithmetic half the input file */
1643
1649
 
1644
1650
                if (UNIV_UNLIKELY(trx_is_interrupted(trx))) {
1645
1651
                        return(DB_INTERRUPTED);
1646
1652
                }
1647
1653
 
 
1654
                /* Remember the offset number for this run */
 
1655
                run_offset[n_run++] = of.offset;
 
1656
 
1648
1657
                error = row_merge_blocks(index, file, block,
1649
1658
                                         &foffs0, &foffs1, &of, table);
1650
1659
 
1652
1661
                        return(error);
1653
1662
                }
1654
1663
 
1655
 
                /* Record the offset of the output file when
1656
 
                approximately half the output has been generated.  In
1657
 
                this way, the next invocation of row_merge() will
1658
 
                spend most of the time in this loop.  The initial
1659
 
                estimate is ohalf==0. */
1660
 
                ahalf = file->offset / 2;
1661
 
                ut_ad(ohalf <= of.offset);
1662
 
 
1663
 
                /* Improve the estimate until reaching half the input
1664
 
                file size, or we can not get any closer to it.  All
1665
 
                comparands should be non-negative when !(ohalf < ahalf)
1666
 
                because ohalf <= of.offset. */
1667
 
                if (ohalf < ahalf || of.offset - ahalf < ohalf - ahalf) {
1668
 
                        ohalf = of.offset;
1669
 
                }
1670
1664
        }
1671
1665
 
1672
1666
        /* Copy the last blocks, if there are any. */
1676
1670
                        return(DB_INTERRUPTED);
1677
1671
                }
1678
1672
 
 
1673
                /* Remember the offset number for this run */
 
1674
                run_offset[n_run++] = of.offset;
 
1675
 
1679
1676
                if (!row_merge_blocks_copy(index, file, block, &foffs0, &of)) {
1680
1677
                        return(DB_CORRUPTION);
1681
1678
                }
1688
1685
                        return(DB_INTERRUPTED);
1689
1686
                }
1690
1687
 
 
1688
                /* Remember the offset number for this run */
 
1689
                run_offset[n_run++] = of.offset;
 
1690
 
1691
1691
                if (!row_merge_blocks_copy(index, file, block, &foffs1, &of)) {
1692
1692
                        return(DB_CORRUPTION);
1693
1693
                }
1699
1699
                return(DB_CORRUPTION);
1700
1700
        }
1701
1701
 
 
1702
        ut_ad(n_run <= *num_run);
 
1703
 
 
1704
        *num_run = n_run;
 
1705
 
 
1706
        /* Each run can contain one or more offsets. As merge goes on,
 
1707
        the number of runs (to merge) will reduce until we have one
 
1708
        single run. So the number of runs will always be smaller than
 
1709
        the number of offsets in file */
 
1710
        ut_ad((*num_run) <= file->offset);
 
1711
 
 
1712
        /* The number of offsets in output file is always equal or
 
1713
        smaller than input file */
 
1714
        ut_ad(of.offset <= file->offset);
 
1715
 
1702
1716
        /* Swap file descriptors for the next pass. */
1703
1717
        *tmpfd = file->fd;
1704
1718
        *file = of;
1705
 
        *half = ohalf;
1706
1719
 
1707
1720
        UNIV_MEM_INVALID(block[0], 3 * sizeof block[0]);
1708
1721
 
1727
1740
                                        if applicable */
1728
1741
{
1729
1742
        ulint   half = file->offset / 2;
 
1743
        ulint   num_runs;
 
1744
        ulint*  run_offset;
 
1745
        ulint   error = DB_SUCCESS;
 
1746
 
 
1747
        /* Record the number of merge runs we need to perform */
 
1748
        num_runs = file->offset;
 
1749
 
 
1750
        /* If num_runs are less than 1, nothing to merge */
 
1751
        if (num_runs <= 1) {
 
1752
                return(error);
 
1753
        }
 
1754
 
 
1755
        /* "run_offset" records each run's first offset number */
 
1756
        run_offset = (ulint*) mem_alloc(file->offset * sizeof(ulint));
 
1757
 
 
1758
        /* This tells row_merge() where to start for the first round
 
1759
        of merge. */
 
1760
        run_offset[half] = half;
1730
1761
 
1731
1762
        /* The file should always contain at least one byte (the end
1732
1763
        of file marker).  Thus, it must be at least one block. */
1733
1764
        ut_ad(file->offset > 0);
1734
1765
 
 
1766
        /* Merge the runs until we have one big run */
1735
1767
        do {
1736
 
                ulint   error;
 
1768
                error = row_merge(trx, index, file, block, tmpfd,
 
1769
                                  table, &num_runs, run_offset);
1737
1770
 
1738
 
                error = row_merge(trx, index, file, &half,
1739
 
                                  block, tmpfd, table);
 
1771
                UNIV_MEM_ASSERT_RW(run_offset, num_runs * sizeof *run_offset);
1740
1772
 
1741
1773
                if (error != DB_SUCCESS) {
1742
 
                        return(error);
 
1774
                        break;
1743
1775
                }
1744
 
 
1745
 
                /* half > 0 should hold except when the file consists
1746
 
                of one block.  No need to merge further then. */
1747
 
                ut_ad(half > 0 || file->offset == 1);
1748
 
        } while (half < file->offset && half > 0);
1749
 
 
1750
 
        return(DB_SUCCESS);
 
1776
        } while (num_runs > 1);
 
1777
 
 
1778
        mem_free(run_offset);
 
1779
 
 
1780
        return(error);
1751
1781
}
1752
1782
 
1753
1783
/*************************************************************//**
1783
1813
                (below). */
1784
1814
                data = btr_rec_copy_externally_stored_field(
1785
1815
                        mrec, offsets, zip_size, i, &len, heap);
 
1816
                /* Because we have locked the table, any records
 
1817
                written by incomplete transactions must have been
 
1818
                rolled back already. There must not be any incomplete
 
1819
                BLOB columns. */
 
1820
                ut_a(data);
1786
1821
 
1787
1822
                dfield_set_data(field, data, len);
1788
1823
        }
2027
2062
 
2028
2063
        ut_ad(index && table && trx);
2029
2064
 
2030
 
        pars_info_add_dulint_literal(info, "indexid", index->id);
 
2065
        pars_info_add_ull_literal(info, "indexid", index->id);
2031
2066
 
2032
2067
        trx_start_if_not_started(trx);
2033
2068
        trx->op_info = "dropping index";
2098
2133
                const rec_t*    rec;
2099
2134
                const byte*     field;
2100
2135
                ulint           len;
2101
 
                dulint          table_id;
 
2136
                table_id_t      table_id;
2102
2137
                dict_table_t*   table;
2103
2138
 
2104
2139
                btr_pcur_move_to_next_user_rec(&pcur, &mtr);
2169
2204
        /* This temp file open does not go through normal
2170
2205
        file APIs, add instrumentation to register with
2171
2206
        performance schema */
2172
 
        struct PSI_file_locker* locker = NULL;
2173
 
        register_pfs_file_open_begin(locker, innodb_file_temp_key,
 
2207
        struct PSI_file_locker* locker = NULL;
 
2208
        PSI_file_locker_state   state;
 
2209
        register_pfs_file_open_begin(&state, locker, innodb_file_temp_key,
2174
2210
                                     PSI_FILE_OPEN,
2175
2211
                                     "Innodb Merge Temp File",
2176
2212
                                     __FILE__, __LINE__);
2192
2228
        merge_file_t*   merge_file)     /*!< out: merge file structure */
2193
2229
{
2194
2230
#ifdef UNIV_PFS_IO
2195
 
        struct PSI_file_locker* locker = NULL;
2196
 
        register_pfs_file_io_begin(locker, merge_file->fd, 0, PSI_FILE_CLOSE,
 
2231
        struct PSI_file_locker* locker = NULL;
 
2232
        PSI_file_locker_state   state;
 
2233
        register_pfs_file_io_begin(&state, locker, merge_file->fd, 0, PSI_FILE_CLOSE,
2197
2234
                                   __FILE__, __LINE__);
2198
2235
#endif
2199
2236
        if (merge_file->fd != -1) {
2325
2362
 
2326
2363
        trx->op_info = "renaming indexes";
2327
2364
 
2328
 
        pars_info_add_dulint_literal(info, "tableid", table->id);
 
2365
        pars_info_add_ull_literal(info, "tableid", table->id);
2329
2366
 
2330
2367
        err = que_eval_sql(info, rename_indexes, FALSE, trx);
2331
2368
 
2362
2399
{
2363
2400
        ulint           err     = DB_ERROR;
2364
2401
        pars_info_t*    info;
2365
 
        const char*     old_name= old_table->name;
 
2402
        char            old_name[MAX_TABLE_NAME_LEN + 1];
2366
2403
 
2367
2404
        ut_ad(trx->mysql_thread_id == os_thread_get_curr_id());
2368
2405
        ut_ad(old_table != new_table);
2370
2407
 
2371
2408
        ut_a(trx->dict_operation_lock_mode == RW_X_LATCH);
2372
2409
 
 
2410
        /* store the old/current name to an automatic variable */
 
2411
        if (strlen(old_table->name) + 1 <= sizeof(old_name)) {
 
2412
                memcpy(old_name, old_table->name, strlen(old_table->name) + 1);
 
2413
        } else {
 
2414
                ut_print_timestamp(stderr);
 
2415
                fprintf(stderr, "InnoDB: too long table name: '%s', "
 
2416
                        "max length is %d\n", old_table->name,
 
2417
                        MAX_TABLE_NAME_LEN);
 
2418
                ut_error;
 
2419
        }
 
2420
 
 
2421
        /* store the old/current name to an automatic variable */
 
2422
        if (strlen(old_table->name) + 1 <= sizeof(old_name)) {
 
2423
                memcpy(old_name, old_table->name, strlen(old_table->name) + 1);
 
2424
        } else {
 
2425
                ut_print_timestamp(stderr);
 
2426
                fprintf(stderr, "InnoDB: too long table name: '%s', "
 
2427
                        "max length is %d\n", old_table->name,
 
2428
                        MAX_TABLE_NAME_LEN);
 
2429
                ut_error;
 
2430
        }
 
2431
 
2373
2432
        trx->op_info = "renaming tables";
2374
2433
 
2375
2434
        /* We use the private SQL parser of Innobase to generate the query
2405
2464
                goto err_exit;
2406
2465
        }
2407
2466
 
2408
 
        err = dict_load_foreigns(old_name, TRUE);
 
2467
        err = dict_load_foreigns(old_name, FALSE, TRUE);
2409
2468
 
2410
2469
        if (err != DB_SUCCESS) {
2411
2470
err_exit:
2502
2561
                /* Note the id of the transaction that created this
2503
2562
                index, we use it to restrict readers from accessing
2504
2563
                this index, to ensure read consistency. */
2505
 
                index->trx_id = (ib_uint64_t)
2506
 
                        ut_conv_dulint_to_longlong(trx->id);
 
2564
                index->trx_id = trx->id;
2507
2565
        } else {
2508
2566
                index = NULL;
2509
2567
        }
2520
2578
        const trx_t*            trx,    /*!< in: transaction */
2521
2579
        const dict_index_t*     index)  /*!< in: index to check */
2522
2580
{
2523
 
        return(!trx->read_view || read_view_sees_trx_id(
2524
 
                       trx->read_view,
2525
 
                       ut_dulint_create((ulint) (index->trx_id >> 32),
2526
 
                                        (ulint) index->trx_id & 0xFFFFFFFF)));
 
2581
        return(!trx->read_view
 
2582
               || read_view_sees_trx_id(trx->read_view, index->trx_id));
2527
2583
}
2528
2584
 
2529
2585
/*********************************************************************//**