mariadb/include/page0page.ic
marko e76b873f24 branches/innodb+: Merge revisions 4660:5090 from branches/zip:
------------------------------------------------------------------------
  r4670 | vasil | 2009-04-07 09:35:23 +0300 (Tue, 07 Apr 2009) | 11 lines

  branches/zip:

  Fix Bug#43660 SHOW INDEXES/ANALYZE does NOT update cardinality for
  indexes of InnoDB table

  by replacing the pseudo random number generator with a better one (LCG).

  This also fixes Mantis Issue#212.

  Approved by:	Heikki (rb://110)
  ------------------------------------------------------------------------
  r4671 | vasil | 2009-04-07 09:37:31 +0300 (Tue, 07 Apr 2009) | 4 lines

  branches/zip:

  Add ChangeLog entry for r4670.
  ------------------------------------------------------------------------
  r4673 | marko | 2009-04-07 15:45:28 +0300 (Tue, 07 Apr 2009) | 4 lines

  branches/zip: Allow in-place updates of UTF-8 CHAR columns
  from or to NULL in ROW_FORMAT=REDUNDANT. (Bug #44032)

  rb://107 approved by Heikki Tuuri.
  ------------------------------------------------------------------------
  r4677 | marko | 2009-04-07 16:19:31 +0300 (Tue, 07 Apr 2009) | 1 line

  branches/zip: Adjust r4673 as in the merge to branches/6.0 -r4676.
  ------------------------------------------------------------------------
  r4678 | inaam | 2009-04-07 18:45:37 +0300 (Tue, 07 Apr 2009) | 12 lines

  branches/zip

  Enable atomics on solaris (using the libc functions as defined in
  atomic.h) if GCC atomic builtins are not present.

  There still remains some work to be done (by Vasil?). This patch
  makes changes to plug.in to check pthread_t size and presence of
  atomic functions when running on solaris. The same has to become
  a part of the generated Makefile.in when we bake our source.

  Reviewed by: Heikki rb://106
  ------------------------------------------------------------------------
  r4687 | vasil | 2009-04-08 13:08:59 +0300 (Wed, 08 Apr 2009) | 4 lines

  branches/zip:

  Whitespace fixup in the ChangeLog
  ------------------------------------------------------------------------
  r4688 | vasil | 2009-04-08 13:11:15 +0300 (Wed, 08 Apr 2009) | 4 lines

  branches/zip:

  Add ChangeLog entry for r4678.
  ------------------------------------------------------------------------
  r4689 | marko | 2009-04-08 14:24:49 +0300 (Wed, 08 Apr 2009) | 5 lines

  branches/zip: Hide unnecessarily visible globals.
  dict_ind_redundant, dict_ind_compact: Declare these UNIV_INTERN.
  innodb_hton_ptr: Declare static.  We do not attempt to access the
  built-in InnoDB any more.
  trx_roll_savepoints_free(): Declare UNIV_INTERN.
  ------------------------------------------------------------------------
  r4700 | calvin | 2009-04-11 00:37:10 +0300 (Sat, 11 Apr 2009) | 9 lines

  branches/zip: Rewrite CMakeLists.txt

  CMakeLists.txt is completely rewritten:
  - To replace the one written by mysql
  - Print out some useful information, such as
    system name, directory, generator used,
    win64, Microsoft compiler, etc.
  - Remove one workaround for mysqld.lib location.
    User does not need to specify a build type
  ------------------------------------------------------------------------
  r4702 | calvin | 2009-04-13 18:16:44 +0300 (Mon, 13 Apr 2009) | 3 lines

  branches/zip: delete the original CMakeLists.txt

  A new version will be committed, suggested by Ken.
  ------------------------------------------------------------------------
  r4703 | calvin | 2009-04-13 18:20:45 +0300 (Mon, 13 Apr 2009) | 9 lines

  branches/zip: new CMakeLists.txt

  CMakeLists.txt is completely rewritten with enhancements:
  - Print out useful information, such as
    system name, directory, generator used,
    win64, Microsoft compiler, etc.
  - Remove one workaround for mysqld.lib location.
    User does not need to specify a build type
    when invoking MSVC generator.
  ------------------------------------------------------------------------
  r4706 | vasil | 2009-04-14 14:32:11 +0300 (Tue, 14 Apr 2009) | 5 lines

  branches/zip:

  When using the random function, first take the modulus by the number of pages
  and then typecast to ulint.
  ------------------------------------------------------------------------
  r4707 | calvin | 2009-04-14 17:47:31 +0300 (Tue, 14 Apr 2009) | 13 lines

  branches/zip: remove statically linked libraries from mysql

  To make zlib and strings dynamically linked; mysqld will export
  additional functions required by InnoDB.

  Since the symbols will be resolved dynamically during runtime,
  wdl_load_mapfile() is no longer able to make any function calls
  to ones in mysqld. As the result, strtoull() (from strings.lib)
  is replaced with _strtoui64().

  rb://111

  Approved by: Marko
  ------------------------------------------------------------------------
  r4712 | vasil | 2009-04-15 12:26:32 +0300 (Wed, 15 Apr 2009) | 157 lines

  branches/zip: Merge revisions 4481:4710 from branches/5.1:

  (resolving conflict in r4574, r4575 and skipping r4699 and r4705 because
  analogous changes to r4699 and r4705 were already made to branches/zip)

    ------------------------------------------------------------------------
    r4573 | vasil | 2009-03-30 14:17:13 +0300 (Mon, 30 Mar 2009) | 4 lines
    Changed paths:
       M /branches/5.1/mysql-test/innodb.test

    branches/5.1:

    Fix email address from dev@innodb.com to innodb_dev_ww@oracle.com

    ------------------------------------------------------------------------
    r4574 | vasil | 2009-03-30 14:27:08 +0300 (Mon, 30 Mar 2009) | 38 lines
    Changed paths:
       M /branches/5.1/Makefile.am
       M /branches/5.1/mysql-test/innodb.test

    branches/5.1:

    Restore the state of INNODB_THREAD_CONCURRENCY to silence this warning:

      TEST                                      RESULT   TIME (ms)
      ------------------------------------------------------------

      worker[1] Using MTR_BUILD_THREAD 250, with reserved ports 12500..12509
      main.innodb                              [ pass ]   8803

      MTR's internal check of the test case 'main.innodb' failed.
      This means that the test case does not preserve the state that existed
      before the test case was executed.  Most likely the test case did not
      do a proper clean-up.
      This is the diff of the states of the servers before and after the
      test case was executed:
      mysqltest: Logging to '/tmp/autotest.sh-20090330_033000-5.1.5Hg8CY/mysql-5.1/mysql-test/var/tmp/check-mysqld_1.log'.
      mysqltest: Results saved in '/tmp/autotest.sh-20090330_033000-5.1.5Hg8CY/mysql-5.1/mysql-test/var/tmp/check-mysqld_1.result'.
      mysqltest: Connecting to server localhost:12500 (socket /tmp/autotest.sh-20090330_033000-5.1.5Hg8CY/mysql-5.1/mysql-test/var/tmp/mysqld.1.sock) as 'root', connection 'default', attempt 0 ...
      mysqltest: ... Connected.
      mysqltest: Start processing test commands from './include/check-testcase.test' ...
      mysqltest: ... Done processing test commands.
      --- /tmp/autotest.sh-20090330_033000-5.1.5Hg8CY/mysql-5.1/mysql-test/var/tmp/check-mysqld_1.result	2009-03-30 14:12:31.000000000 +0300
      +++ /tmp/autotest.sh-20090330_033000-5.1.5Hg8CY/mysql-5.1/mysql-test/var/tmp/check-mysqld_1.reject	2009-03-30 14:12:41.000000000 +0300
      @@ -99,7 +99,7 @@
       INNODB_SUPPORT_XA	ON
       INNODB_SYNC_SPIN_LOOPS	20
       INNODB_TABLE_LOCKS	ON
      -INNODB_THREAD_CONCURRENCY	8
      +INNODB_THREAD_CONCURRENCY	16
       INNODB_THREAD_SLEEP_DELAY	10000
       INSERT_ID	0
       INTERACTIVE_TIMEOUT	28800

      mysqltest: Result content mismatch

      not ok
    ------------------------------------------------------------------------
    r4575 | vasil | 2009-03-30 15:55:31 +0300 (Mon, 30 Mar 2009) | 8 lines
    Changed paths:
       M /branches/5.1/mysql-test/innodb.result
       M /branches/5.1/mysql-test/innodb.test

    branches/5.1:

    Fix Bug#43309 Test main.innodb can't be run twice

    Make the innodb mysql-test more flexible by inspecting how much a
    variable of interest has changed since the start of the test. Do not
    assume the variables have zero values at the start of the test.
    ------------------------------------------------------------------------
    r4576 | vasil | 2009-03-30 16:25:10 +0300 (Mon, 30 Mar 2009) | 4 lines
    Changed paths:
       M /branches/5.1/Makefile.am

    branches/5.1:

    Revert a change to Makefile.am that I committed accidentally in c4574.
    ------------------------------------------------------------------------
    r4659 | vasil | 2009-04-06 15:34:51 +0300 (Mon, 06 Apr 2009) | 6 lines
    Changed paths:
       M /branches/5.1/mysql-test/innodb.test

    branches/5.1:

    Followup to r4575 and the fix of Bug#43309 Test main.innodb can't be run twice:

    Add an explanatory comment, as suggested by Patrick Crews in the bug report.
    ------------------------------------------------------------------------
    r4699 | vasil | 2009-04-09 14:01:52 +0300 (Thu, 09 Apr 2009) | 15 lines
    Changed paths:
       M /branches/5.1/handler/ha_innodb.cc
       M /branches/5.1/include/srv0srv.h
       M /branches/5.1/page/page0cur.c
       M /branches/5.1/srv/srv0srv.c

    branches/5.1:

    Fix Bug#43660 SHOW INDEXES/ANALYZE does NOT update cardinality for indexes
    of InnoDB table

    by replacing the PRNG that is used to pick random pages with a better
    one.

    This is based on r4670 but also adds a new configuration option and
    enables the fix only if this option is changed. Please skip the present
    revision when merging.

    Approved by:	Heikki (via email)
    ------------------------------------------------------------------------
    r4705 | vasil | 2009-04-14 14:30:13 +0300 (Tue, 14 Apr 2009) | 5 lines
    Changed paths:
       M /branches/5.1/page/page0cur.c

    branches/5.1:

    When using the random function, first take the modulus by the number of pages
    and then typecast to ulint.

    ------------------------------------------------------------------------
    r4710 | vasil | 2009-04-15 11:55:18 +0300 (Wed, 15 Apr 2009) | 25 lines
    Changed paths:
       M /branches/5.1/handler/ha_innodb.cc

    branches/5.1:

    Merge a change from MySQL (looks like this is against 5.0 but they later
    merged it to 5.1):

      ------------------------------------------------------------
      revno: 1810.3846.1
      committer: Alexey Botchkov <holyfoot@mysql.com>
      branch nick: 31435
      timestamp: Tue 2008-11-11 14:42:32 +0400
      message:
        Bug#31435 ha_innodb.cc:3983: ulint convert_search_mode_to_innobase(ha_rkey_function): Asse 
            I think we don't need to issue an error statement in the convert_search_mode_to_innobase().
            Returning the PAGE_CUR_UNSUPP value is enough as allows to handle this
            case depending on the requirements.

        per-file comments:
          sql/ha_innodb.cc 
        Bug#31435 ha_innodb.cc:3983: ulint convert_search_mode_to_innobase(ha_rkey_function): Asse 
             no error issued in convert_search_mode_to_innobase.
             ha_innobase::records_in_range() returns HA_POS_ERROR if search mode isn't supported.
      modified:
        sql/ha_innodb.cc
    ------------------------------------------------------------------------
  ------------------------------------------------------------------------
  r4713 | vasil | 2009-04-15 12:36:16 +0300 (Wed, 15 Apr 2009) | 4 lines

  branches/zip:

  Add missing ChangeLog entries
  ------------------------------------------------------------------------
  r4714 | vasil | 2009-04-15 12:36:57 +0300 (Wed, 15 Apr 2009) | 4 lines

  branches/zip:

  Fix typo in the ChangeLog
  ------------------------------------------------------------------------
  r4715 | vasil | 2009-04-15 12:39:04 +0300 (Wed, 15 Apr 2009) | 4 lines

  branches/zip:

  Whitespace cleanup in ChangeLog
  ------------------------------------------------------------------------
  r4716 | vasil | 2009-04-15 21:36:06 +0300 (Wed, 15 Apr 2009) | 4 lines

  branches/zip:

  Add ChangeLog entry for r4543.
  ------------------------------------------------------------------------
  r4717 | calvin | 2009-04-16 01:22:35 +0300 (Thu, 16 Apr 2009) | 18 lines

  branches/zip: Use the Windows Interlocked functions for atomic memory
  access

  Mapping the atomic operations to Windows Interlocked functions:

  os_compare_and_swap_* to InterlockedCompareExchange(64)
  os_atomic_increment_* to InterlockedExchangeAdd(64)
  os_atomic_test_and_set_byte to InterlockedExchange

  In this patch, the legacy code under UNIV_CAN_USE_X86_ASSEMBLER is
  removed all together, and add HAVE_WINDOWS_ATOMICS and
  INNODB_RW_LOCKS_USE_ATOMICS to CMakeLists.txt

  This is to address mantis issue#194.

  rb://113

  Approved by: Marko
  ------------------------------------------------------------------------
  r4720 | vasil | 2009-04-16 09:44:48 +0300 (Thu, 16 Apr 2009) | 4 lines

  branches/zip:

  Add ChangeLog entry for r4717.
  ------------------------------------------------------------------------
  r4721 | marko | 2009-04-16 10:32:09 +0300 (Thu, 16 Apr 2009) | 2 lines

  branches/zip: row_scan_and_check_index(): Initialize prebuilt->index_usable.
  This should have been done in r4631.  Spotted by Michael.
  ------------------------------------------------------------------------
  r4728 | marko | 2009-04-16 16:02:27 +0300 (Thu, 16 Apr 2009) | 3 lines

  branches/zip: univ.i: Define REFMAN as the base URL of the
  MySQL Reference Manual and use it in every string.
  This fixes Issue #221.
  ------------------------------------------------------------------------
  r4733 | calvin | 2009-04-17 08:13:20 +0300 (Fri, 17 Apr 2009) | 6 lines

  branches/zip: minor changes to CMakeLists.txt

  All are non-functional changes:
  - should check for long (not int), spotted by Sunny
  - comment out the project definition, avoiding to generate another
    .sln file.
  ------------------------------------------------------------------------
  r4748 | vasil | 2009-04-18 00:50:09 +0300 (Sat, 18 Apr 2009) | 118 lines

  branches/zip: Merge revisions 4710:4746 from branches/5.1:

    ------------------------------------------------------------------------
    r4746 | vasil | 2009-04-18 00:32:08 +0300 (Sat, 18 Apr 2009) | 110 lines
    Changed paths:
       M /branches/5.1/handler/ha_innodb.cc
       M /branches/5.1/include/pars0pars.h

    branches/5.1:

    Merge a change from MySQL:

      ------------------------------------------------------------
      revno: 2728.10.2
      committer: Ignacio Galarza <iggy@mysql.com>
      branch nick: mysql-5.1-bugteam-bug29125
      timestamp: Fri 2009-02-13 11:41:47 -0500
      message:
        Bug#29125 Windows Server X64: so many compiler warnings
        - Remove bothersome warning messages.  This change focuses on the warnings 
        that are covered by the ignore file: support-files/compiler_warnings.supp.
        - Strings are guaranteed to be max uint in length
      modified:
        client/mysql_upgrade.c
        client/mysqladmin.cc
        client/mysqlbinlog.cc
        client/mysqlcheck.c
        client/mysqldump.c
        client/mysqlslap.c
        client/mysqltest.cc
        client/sql_string.cc
        extra/comp_err.c
        extra/yassl/src/buffer.cpp
        extra/yassl/taocrypt/include/block.hpp
        extra/yassl/taocrypt/src/algebra.cpp
        extra/yassl/taocrypt/src/asn.cpp
        include/config-win.h
        libmysql/libmysql.c
        mysys/array.c
        mysys/base64.c
        mysys/charset.c
        mysys/checksum.c
        mysys/default.c
        mysys/default_modify.c
        mysys/hash.c
        mysys/mf_keycache.c
        mysys/mf_tempdir.c
        mysys/my_append.c
        mysys/my_compress.c
        mysys/my_conio.c
        mysys/my_copy.c
        mysys/my_getwd.c
        mysys/my_pread.c
        mysys/my_quick.c
        mysys/my_read.c
        mysys/safemalloc.c
        mysys/string.c
        server-tools/instance-manager/buffer.cc
        server-tools/instance-manager/instance.cc
        server-tools/instance-manager/options.cc
        server-tools/instance-manager/parse.h
        sql-common/client.c
        sql-common/my_user.c
        sql/event_data_objects.cc
        sql/event_parse_data.cc
        sql/events.cc
        sql/gen_lex_hash.cc
        sql/item.h
        sql/item_func.cc
        sql/item_strfunc.cc
        sql/item_timefunc.cc
        sql/lock.cc
        sql/log_event.cc
        sql/log_event.h
        sql/log_event_old.cc
        sql/net_serv.cc
        sql/sp_head.h
        sql/spatial.h
        sql/sql_class.h
        sql/sql_connect.cc
        sql/sql_crypt.cc
        sql/sql_error.cc
        sql/sql_insert.cc
        sql/sql_lex.cc
        sql/sql_lex.h
        sql/sql_load.cc
        sql/sql_prepare.cc
        sql/sql_profile.cc
        sql/sql_repl.cc
        sql/sql_servers.cc
        sql/sql_string.cc
        sql/sql_table.cc
        sql/sql_trigger.cc
        sql/sql_udf.cc
        sql/sql_view.cc
        sql/udf_example.c
        sql/uniques.cc
        storage/archive/azio.c
        storage/archive/azlib.h
        storage/csv/ha_tina.cc
        storage/csv/ha_tina.h
        storage/csv/transparent_file.h
        storage/federated/ha_federated.cc
        storage/federated/ha_federated.h
        storage/heap/hp_write.c
        storage/innobase/handler/ha_innodb.cc
        storage/innobase/include/pars0pars.h
        storage/myisam/ha_myisam.cc
        storage/myisam/mi_check.c
        storage/myisam/mi_packrec.c
        storage/myisam/mi_search.c
        storage/myisam/rt_index.c
        storage/myisammrg/ha_myisammrg.cc
        strings/ctype.c
        strings/my_vsnprintf.c
        tests/bug25714.c
        tests/mysql_client_test.c
  ------------------------------------------------------------------------
  r4749 | vasil | 2009-04-18 00:58:08 +0300 (Sat, 18 Apr 2009) | 4 lines

  branches/zip:

  Add ChangeLog entry for t4748.
  ------------------------------------------------------------------------
  r4751 | vasil | 2009-04-18 01:29:16 +0300 (Sat, 18 Apr 2009) | 4 lines

  branches/zip:

  Silence warning about unused variables.
  ------------------------------------------------------------------------
  r4752 | vasil | 2009-04-18 01:30:37 +0300 (Sat, 18 Apr 2009) | 4 lines

  branches/zip:

  Include the needed header for memset().
  ------------------------------------------------------------------------
  r4753 | vasil | 2009-04-18 01:31:34 +0300 (Sat, 18 Apr 2009) | 4 lines

  branches/zip:

  Silence a compiler warning.
  ------------------------------------------------------------------------
  r4756 | vasil | 2009-04-18 02:19:03 +0300 (Sat, 18 Apr 2009) | 5 lines

  branches/zip:

  Rename the aux config program and give it a more specific name because
  more are coming.
  ------------------------------------------------------------------------
  r4757 | vasil | 2009-04-18 02:22:33 +0300 (Sat, 18 Apr 2009) | 4 lines

  branches/zip:

  Add comment and copyright notice to the aux config program.
  ------------------------------------------------------------------------
  r4758 | vasil | 2009-04-18 02:40:47 +0300 (Sat, 18 Apr 2009) | 5 lines

  branches/zip:

  Add aux config programs to emulate the newly added checks in plug.in
  (from r4678).
  ------------------------------------------------------------------------
  r4830 | marko | 2009-04-20 16:11:38 +0300 (Mon, 20 Apr 2009) | 6 lines

  branches/zip: Cosmetic fixes.

  row_unlock_for_mysql(): Add a const qualifier to read-only rec_t*.
  Use dict_index_is_clust().

  CMakeLists.txt: svn propset svn:eol-style native.
  ------------------------------------------------------------------------
  r4893 | marko | 2009-04-23 09:32:36 +0300 (Thu, 23 Apr 2009) | 11 lines

  branches/zip: Introduce the logical type names trx_id_t, roll_ptr_t,
  and undo_no_t. Each type is still defined as dulint.

  This is an initial step towards replacing dulint with a 64-bit data type.
  Because modern compilers have no trouble supporting 64-bit arithmetics
  even on 32-bit targets, the dulint struct is a relic that should go.

  The last remaining major use of dulint is dictionary IDs
  (table, index, and row ids).

  rb://114 approved by Sunny Bains
  ------------------------------------------------------------------------
  r4894 | marko | 2009-04-23 10:21:07 +0300 (Thu, 23 Apr 2009) | 1 line

  branches/zip: ChangeLog: Document r4893.
  ------------------------------------------------------------------------
  r4895 | marko | 2009-04-23 10:22:06 +0300 (Thu, 23 Apr 2009) | 1 line

  branches/zip: ChangeLog: Add the missing include/ to two files.
  ------------------------------------------------------------------------
  r4896 | marko | 2009-04-23 10:37:40 +0300 (Thu, 23 Apr 2009) | 4 lines

  branches/zip: row_scan_and_check_index(): Improve the diagnostics, by reporting
  errors from row_search_for_mysql() in the error log.
  The errors will still be ignored by CHECK TABLE.
  This is somewhat related to Issue #211.
  ------------------------------------------------------------------------
  r4897 | marko | 2009-04-23 10:40:34 +0300 (Thu, 23 Apr 2009) | 2 lines

  branches/zip: row_scan_and_check_index(): Check
  row_merge_is_index_usable() earlier, to make the logic clearer.
  ------------------------------------------------------------------------
  r4898 | marko | 2009-04-23 15:15:07 +0300 (Thu, 23 Apr 2009) | 4 lines

  branches/zip: Correct a misleading comment.  PAGE_MAX_TRX_ID
  will be updated in ibuf_insert_low() and updated from the
  insert buffer tree page to the secondary index tree page
  during the insert buffer merge.
  ------------------------------------------------------------------------
  r4915 | marko | 2009-04-27 13:40:20 +0300 (Mon, 27 Apr 2009) | 2 lines

  branches/zip: row_scan_and_check_index(): Add some comments on
  prebuilt->index_usable, as suggested by Michael.
  ------------------------------------------------------------------------
  r4921 | marko | 2009-04-29 11:51:25 +0300 (Wed, 29 Apr 2009) | 2 lines

  branches/zip: btr_cur_optimistic_insert(): Remove a redundant condition.
  The insert buffer tree is a clustered index.
  ------------------------------------------------------------------------
  r4922 | marko | 2009-04-29 23:23:27 +0300 (Wed, 29 Apr 2009) | 22 lines

  branches/zip: Distinguish temporary tables in MLOG_FILE_CREATE.
  This addresses Mantis Issue #23 in InnoDB Hot Backup and some
  of MySQL Bug #41609.

  In MLOG_FILE_CREATE, we need to distinguish temporary tables, so that
  InnoDB Hot Backup can work correctly.  It turns out that we can do this
  easily, by using a bit of the previously unused parameter for page number.
  (The page number parameter of MLOG_FILE_CREATE has been written as 0 
  ever since MySQL 4.1, which introduced MLOG_FILE_CREATE.)

  MLOG_FILE_FLAG_TEMP: A flag for indicating a temporary table in
  the page number parameter of MLOG_FILE_ operations.

  fil_op_write_log(): Add the parameter log_flags.

  fil_op_log_parse_or_replay(): Add the parameter log_flags.
  Do not replay MLOG_FILE_CREATE when MLOG_FILE_FLAG_TEMP is set in log_flags.
  This only affects ibbackup --apply-log.  InnoDB itself never replays file
  operations.

  rb://117 approved by Heikki Tuuri
  ------------------------------------------------------------------------
  r4977 | marko | 2009-05-13 15:49:38 +0300 (Wed, 13 May 2009) | 12 lines

  branches/zip: Merge revisions 4746:4976 from branches/5.1:

    ------------------------------------------------------------------------
    r4976 | marko | 2009-05-13 15:44:54 +0300 (Wed, 13 May 2009) | 6 lines

    branches/5.1: Display DB_ROLL_PTR in the COLUMNS section of the
    innodb_table_monitor output.  It was accidentally omitted due to an
    off-by-one loop condition.  (Bug #44320)

    rb://116 approved by Heikki Tuuri
    ------------------------------------------------------------------------
  ------------------------------------------------------------------------
  r4978 | vasil | 2009-05-13 16:21:55 +0300 (Wed, 13 May 2009) | 4 lines

  branches/zip:

  Add ChangeLog entry for r4977.

  ------------------------------------------------------------------------
  r4995 | marko | 2009-05-14 15:31:43 +0300 (Thu, 14 May 2009) | 24 lines

  branches/zip: Merge revisions 4976:4994 from branches/5.1:

    ------------------------------------------------------------------------
    r4994 | marko | 2009-05-14 15:04:55 +0300 (Thu, 14 May 2009) | 18 lines

    branches/5.1: Prevent a race condition in innobase_commit() by ensuring
    that innodb_commit_concurrency>0 remains constant at run time. (Bug #42101)

    srv_commit_concurrency: Make this a static variable in ha_innodb.cc.

    innobase_commit_concurrency_validate(): Check that innodb_commit_concurrency
    is not changed from or to 0 at run time.  This is needed, because
    innobase_commit() assumes that innodb_commit_concurrency>0 remains constant.
    Without this limitation, the checks for innodb_commit_concurrency>0
    in innobase_commit() should be removed and that function would have to
    acquire and release commit_cond_m at least twice per invocation.
    Normally, innodb_commit_concurrency=0, and introducing the mutex operations
    would mean significant overhead.

    innodb_bug42101.test, innodb_bug42101-nonzero.test: Test cases.

    rb://123 approved by Heikki Tuuri
    ------------------------------------------------------------------------
  ------------------------------------------------------------------------
  r5000 | vasil | 2009-05-14 20:13:41 +0300 (Thu, 14 May 2009) | 4 lines

  branches/zip:

  Add ChangeLog entry for r4994.
  ------------------------------------------------------------------------
  r5026 | marko | 2009-05-18 16:29:51 +0300 (Mon, 18 May 2009) | 1 line

  branches/zip: buf_validate(): Add missing out: comment.
  ------------------------------------------------------------------------
  r5027 | marko | 2009-05-18 16:36:10 +0300 (Mon, 18 May 2009) | 1 line

  branches/zip: Add some missing out: comments to buf0buf.h, buf0buf.c.
  ------------------------------------------------------------------------
  r5028 | marko | 2009-05-18 16:40:07 +0300 (Mon, 18 May 2009) | 11 lines

  branches/zip: When executing an optimistic update by delete-and-insert,
  correctly estimate the free space on the compressed page by
  page_zip_available(..., create=TRUE). This was reported as Issue #231.

  btr_cur_update_alloc_zip(): Add the parameter ibool create and pass it
  to page_zip_available(). The parameter was previously passed as 0.

  btr_cur_optimistic_update(): Pass create=TRUE to btr_cur_update_alloc_zip().

  rb://120 approved by Heikki Tuuri
  ------------------------------------------------------------------------
  r5030 | marko | 2009-05-19 10:04:04 +0300 (Tue, 19 May 2009) | 2 lines

  branches/zip: os_thread_get_curr_id(), os_thread_get_curr():
  Add missing out: comments.
  ------------------------------------------------------------------------
  r5031 | marko | 2009-05-19 10:30:02 +0300 (Tue, 19 May 2009) | 1 line

  branches/zip: Add missing out: comments to nullary functions.
  ------------------------------------------------------------------------
  r5033 | marko | 2009-05-19 11:00:51 +0300 (Tue, 19 May 2009) | 1 line

  branches/zip: Remove bogus out: comments of functions returning void.
  ------------------------------------------------------------------------
  r5034 | marko | 2009-05-19 12:41:32 +0300 (Tue, 19 May 2009) | 1 line

  branches/zip: row_update_prebuilt_trx(): Correct bogus comment.
  ------------------------------------------------------------------------
  r5035 | marko | 2009-05-19 13:04:58 +0300 (Tue, 19 May 2009) | 3 lines

  branches/zip: ut0auxconf_have_solaris_atomics.c: Get the
  function declarations from <atomic.h>.
  Call the functions with proper arguments.
  ------------------------------------------------------------------------
  r5036 | marko | 2009-05-19 13:05:50 +0300 (Tue, 19 May 2009) | 1 line

  branches/zip: Add proper comments to some file page accessors.
  ------------------------------------------------------------------------
  r5037 | marko | 2009-05-19 13:08:16 +0300 (Tue, 19 May 2009) | 1 line

  branches/zip: Fix a typo that was introduced in r5036.
  ------------------------------------------------------------------------
  r5038 | marko | 2009-05-19 22:59:07 +0300 (Tue, 19 May 2009) | 30 lines

  branches/zip: Write PAGE_MAX_TRX_ID to the redo log. Otherwise,
  transactions that are started before the rollback of incomplete
  transactions has finished may have an inconsistent view of the
  secondary indexes.

  dict_index_is_sec_or_ibuf(): Auxiliary function for controlling
  updates and checks of PAGE_MAX_TRX_ID: check whether an index is a
  secondary index or the insert buffer tree.

  page_set_max_trx_id(), page_update_max_trx_id(),
  lock_rec_insert_check_and_lock(),
  lock_sec_rec_modify_check_and_lock(), btr_cur_ins_lock_and_undo(),
  btr_cur_upd_lock_and_undo(): Add the parameter mtr.

  page_set_max_trx_id(): Allow mtr to be NULL.  When mtr==NULL, do not
  attempt to write to the redo log.  This only occurs when creating a
  page or reorganizing a compressed page.  In these cases, the
  PAGE_MAX_TRX_ID will be set correctly during the application of redo
  log records, even though there is no explicit log record about it.

  btr_discard_only_page_on_level(): Preserve PAGE_MAX_TRX_ID.  This
  function should be unreachable, though.

  btr_cur_pessimistic_update(): Update PAGE_MAX_TRX_ID.

  Add some assertions for checking that PAGE_MAX_TRX_ID is set on all
  secondary index leaf pages.

  rb://115 tested by Michael, fixes Issue #211
  ------------------------------------------------------------------------
  r5039 | marko | 2009-05-19 23:13:12 +0300 (Tue, 19 May 2009) | 1 line

  branches/zip: ib_wqueue_wait(): Add decorative comment.
  ------------------------------------------------------------------------
  r5041 | marko | 2009-05-20 08:42:12 +0300 (Wed, 20 May 2009) | 1 line

  branches/zip: Add missing function comments.
  ------------------------------------------------------------------------
  r5042 | marko | 2009-05-20 08:46:01 +0300 (Wed, 20 May 2009) | 1 line

  branches/zip: sync0rw.ic: Remove an extra ; that was added in r5041.
  ------------------------------------------------------------------------
  r5044 | marko | 2009-05-20 11:11:58 +0300 (Wed, 20 May 2009) | 2 lines

  branches/zip: mlog_parse_index(): Correct a parameter comment
  and add a const qualifier that was missing.
  ------------------------------------------------------------------------
  r5045 | marko | 2009-05-20 11:37:08 +0300 (Wed, 20 May 2009) | 1 line

  branches/zip: fil0fil.c: Correct some comments.
  ------------------------------------------------------------------------
  r5046 | marko | 2009-05-20 12:19:40 +0300 (Wed, 20 May 2009) | 1 line

  branches/zip: Fix some function comments.
  ------------------------------------------------------------------------
  r5047 | marko | 2009-05-20 12:26:49 +0300 (Wed, 20 May 2009) | 1 line

  branches/zip: ut_snprintf(): Fix the function comments.
  ------------------------------------------------------------------------
  r5048 | marko | 2009-05-20 12:28:44 +0300 (Wed, 20 May 2009) | 3 lines

  branches/zip: inno_bcmp(): Remove this memcmp replacement.
  srv0start.c does not (any longer) call memcmp.
  srv_parse_megabytes(): Add a function comment.
  ------------------------------------------------------------------------
  r5052 | marko | 2009-05-20 12:32:37 +0300 (Wed, 20 May 2009) | 1 line

  branches/zip: ib_vector_is_empty(): Fix the function comment.
  ------------------------------------------------------------------------
  r5054 | marko | 2009-05-20 12:35:33 +0300 (Wed, 20 May 2009) | 1 line

  branches/zip: page_cur_lcg_prng(): Add missing parameter list.
  ------------------------------------------------------------------------
  r5057 | marko | 2009-05-20 12:45:17 +0300 (Wed, 20 May 2009) | 1 line

  branches/zip: Remove bogus in: comments from struct members.
  ------------------------------------------------------------------------
  r5058 | marko | 2009-05-20 13:06:03 +0300 (Wed, 20 May 2009) | 1 line

  branches/zip: Clean up some function comments.
  ------------------------------------------------------------------------
  r5060 | marko | 2009-05-20 14:06:59 +0300 (Wed, 20 May 2009) | 1 line

  branches/zip: Clean up some comments.
  ------------------------------------------------------------------------
  r5061 | marko | 2009-05-20 14:07:49 +0300 (Wed, 20 May 2009) | 2 lines

  branches/zip: innodb_export_status(): Remove the return(0),
  now that the function was declared void in r5060.
  ------------------------------------------------------------------------
  r5062 | marko | 2009-05-20 14:45:03 +0300 (Wed, 20 May 2009) | 1 line

  branches/zip: ha_innodb.cc: Clean up some comments.
  ------------------------------------------------------------------------
  r5063 | marko | 2009-05-20 16:10:17 +0300 (Wed, 20 May 2009) | 1 line

  branches/zip: ut_dulint_sort(): Write proper comments.
  ------------------------------------------------------------------------
  r5064 | marko | 2009-05-20 16:17:26 +0300 (Wed, 20 May 2009) | 2 lines

  branches/zip: innobase_end(), innobase_flush_logs():
  Document the function parameters.
  ------------------------------------------------------------------------
  r5065 | marko | 2009-05-20 23:17:43 +0300 (Wed, 20 May 2009) | 1 line

  branches/zip: ha_innodb.cc: Add some missing function comments.
  ------------------------------------------------------------------------
  r5066 | marko | 2009-05-21 00:51:23 +0300 (Thu, 21 May 2009) | 2 lines

  branches/zip: Fix some function comments.
  ------------------------------------------------------------------------
  r5070 | vasil | 2009-05-21 08:27:00 +0300 (Thu, 21 May 2009) | 4 lines

  branches/zip:

  Whitespace fixup.
  ------------------------------------------------------------------------
2009-05-25 06:20:53 +00:00

1079 lines
29 KiB
Text

/*****************************************************************************
Copyright (c) 1994, 2009, Innobase Oy. All Rights Reserved.
This program is free software; you can redistribute it and/or modify it under
the terms of the GNU General Public License as published by the Free Software
Foundation; version 2 of the License.
This program is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
You should have received a copy of the GNU General Public License along with
this program; if not, write to the Free Software Foundation, Inc., 59 Temple
Place, Suite 330, Boston, MA 02111-1307 USA
*****************************************************************************/
/******************************************************
Index page routines
Created 2/2/1994 Heikki Tuuri
*******************************************************/
#include "mach0data.h"
#ifdef UNIV_DEBUG
# include "log0recv.h"
#endif /* !UNIV_DEBUG */
#ifndef UNIV_HOTBACKUP
# include "rem0cmp.h"
#endif /* !UNIV_HOTBACKUP */
#include "mtr0log.h"
#include "page0zip.h"
#ifdef UNIV_MATERIALIZE
#undef UNIV_INLINE
#define UNIV_INLINE
#endif
/****************************************************************
Gets the start of a page. */
UNIV_INLINE
page_t*
page_align(
/*=======*/
/* out: start of the page */
const void* ptr) /* in: pointer to page frame */
{
return((page_t*) ut_align_down(ptr, UNIV_PAGE_SIZE));
}
/****************************************************************
Gets the offset within a page. */
UNIV_INLINE
ulint
page_offset(
/*========*/
/* out: offset from the start of the page */
const void* ptr) /* in: pointer to page frame */
{
return(ut_align_offset(ptr, UNIV_PAGE_SIZE));
}
/*****************************************************************
Returns the max trx id field value. */
UNIV_INLINE
trx_id_t
page_get_max_trx_id(
/*================*/
const page_t* page) /* in: page */
{
ut_ad(page);
return(mach_read_from_8(page + PAGE_HEADER + PAGE_MAX_TRX_ID));
}
/*****************************************************************
Sets the max trx id field value if trx_id is bigger than the previous
value. */
UNIV_INLINE
void
page_update_max_trx_id(
/*===================*/
buf_block_t* block, /* in/out: page */
page_zip_des_t* page_zip,/* in/out: compressed page whose
uncompressed part will be updated, or NULL */
trx_id_t trx_id, /* in: transaction id */
mtr_t* mtr) /* in/out: mini-transaction */
{
ut_ad(block);
ut_ad(mtr_memo_contains(mtr, block, MTR_MEMO_PAGE_X_FIX));
/* During crash recovery, this function may be called on
something else than a leaf page of a secondary index or the
insert buffer index tree (dict_index_is_sec_or_ibuf() returns
TRUE for the dummy indexes constructed during redo log
application). In that case, PAGE_MAX_TRX_ID is unused,
and trx_id is usually zero. */
ut_ad(!ut_dulint_is_zero(trx_id) || recv_recovery_is_on());
ut_ad(page_is_leaf(buf_block_get_frame(block)));
if (ut_dulint_cmp(page_get_max_trx_id(buf_block_get_frame(block)),
trx_id) < 0) {
page_set_max_trx_id(block, page_zip, trx_id, mtr);
}
}
/*****************************************************************
Reads the given header field. */
UNIV_INLINE
ulint
page_header_get_field(
/*==================*/
const page_t* page, /* in: page */
ulint field) /* in: PAGE_LEVEL, ... */
{
ut_ad(page);
ut_ad(field <= PAGE_INDEX_ID);
return(mach_read_from_2(page + PAGE_HEADER + field));
}
/*****************************************************************
Sets the given header field. */
UNIV_INLINE
void
page_header_set_field(
/*==================*/
page_t* page, /* in/out: page */
page_zip_des_t* page_zip,/* in/out: compressed page whose
uncompressed part will be updated, or NULL */
ulint field, /* in: PAGE_N_DIR_SLOTS, ... */
ulint val) /* in: value */
{
ut_ad(page);
ut_ad(field <= PAGE_N_RECS);
ut_ad(field == PAGE_N_HEAP || val < UNIV_PAGE_SIZE);
ut_ad(field != PAGE_N_HEAP || (val & 0x7fff) < UNIV_PAGE_SIZE);
mach_write_to_2(page + PAGE_HEADER + field, val);
if (UNIV_LIKELY_NULL(page_zip)) {
page_zip_write_header(page_zip,
page + PAGE_HEADER + field, 2, NULL);
}
}
/*****************************************************************
Returns the offset stored in the given header field. */
UNIV_INLINE
ulint
page_header_get_offs(
/*=================*/
/* out: offset from the start of the page,
or 0 */
const page_t* page, /* in: page */
ulint field) /* in: PAGE_FREE, ... */
{
ulint offs;
ut_ad(page);
ut_ad((field == PAGE_FREE)
|| (field == PAGE_LAST_INSERT)
|| (field == PAGE_HEAP_TOP));
offs = page_header_get_field(page, field);
ut_ad((field != PAGE_HEAP_TOP) || offs);
return(offs);
}
/*****************************************************************
Sets the pointer stored in the given header field. */
UNIV_INLINE
void
page_header_set_ptr(
/*================*/
page_t* page, /* in: page */
page_zip_des_t* page_zip,/* in/out: compressed page whose
uncompressed part will be updated, or NULL */
ulint field, /* in: PAGE_FREE, ... */
const byte* ptr) /* in: pointer or NULL*/
{
ulint offs;
ut_ad(page);
ut_ad((field == PAGE_FREE)
|| (field == PAGE_LAST_INSERT)
|| (field == PAGE_HEAP_TOP));
if (ptr == NULL) {
offs = 0;
} else {
offs = ptr - page;
}
ut_ad((field != PAGE_HEAP_TOP) || offs);
page_header_set_field(page, page_zip, field, offs);
}
#ifndef UNIV_HOTBACKUP
/*****************************************************************
Resets the last insert info field in the page header. Writes to mlog
about this operation. */
UNIV_INLINE
void
page_header_reset_last_insert(
/*==========================*/
page_t* page, /* in/out: page */
page_zip_des_t* page_zip,/* in/out: compressed page whose
uncompressed part will be updated, or NULL */
mtr_t* mtr) /* in: mtr */
{
ut_ad(page && mtr);
if (UNIV_LIKELY_NULL(page_zip)) {
mach_write_to_2(page + (PAGE_HEADER + PAGE_LAST_INSERT), 0);
page_zip_write_header(page_zip,
page + (PAGE_HEADER + PAGE_LAST_INSERT),
2, mtr);
} else {
mlog_write_ulint(page + (PAGE_HEADER + PAGE_LAST_INSERT), 0,
MLOG_2BYTES, mtr);
}
}
#endif /* !UNIV_HOTBACKUP */
/****************************************************************
Determine whether the page is in new-style compact format. */
UNIV_INLINE
ulint
page_is_comp(
/*=========*/
/* out: nonzero if the page is in compact
format, zero if it is in old-style format */
const page_t* page) /* in: index page */
{
return(UNIV_EXPECT(page_header_get_field(page, PAGE_N_HEAP) & 0x8000,
0x8000));
}
/****************************************************************
TRUE if the record is on a page in compact format. */
UNIV_INLINE
ulint
page_rec_is_comp(
/*=============*/
/* out: nonzero if in compact format */
const rec_t* rec) /* in: record */
{
return(page_is_comp(page_align(rec)));
}
/*******************************************************************
Returns the heap number of a record. */
UNIV_INLINE
ulint
page_rec_get_heap_no(
/*=================*/
/* out: heap number */
const rec_t* rec) /* in: the physical record */
{
if (page_rec_is_comp(rec)) {
return(rec_get_heap_no_new(rec));
} else {
return(rec_get_heap_no_old(rec));
}
}
/****************************************************************
Determine whether the page is a B-tree leaf. */
UNIV_INLINE
ibool
page_is_leaf(
/*=========*/
/* out: TRUE if the page is a B-tree leaf */
const page_t* page) /* in: page */
{
return(!*(const uint16*) (page + (PAGE_HEADER + PAGE_LEVEL)));
}
/****************************************************************
Gets the offset of the first record on the page. */
UNIV_INLINE
ulint
page_get_infimum_offset(
/*====================*/
/* out: offset of the first record
in record list, relative from page */
const page_t* page) /* in: page which must have record(s) */
{
ut_ad(page);
ut_ad(!page_offset(page));
if (page_is_comp(page)) {
return(PAGE_NEW_INFIMUM);
} else {
return(PAGE_OLD_INFIMUM);
}
}
/****************************************************************
Gets the offset of the last record on the page. */
UNIV_INLINE
ulint
page_get_supremum_offset(
/*=====================*/
/* out: offset of the last record in
record list, relative from page */
const page_t* page) /* in: page which must have record(s) */
{
ut_ad(page);
ut_ad(!page_offset(page));
if (page_is_comp(page)) {
return(PAGE_NEW_SUPREMUM);
} else {
return(PAGE_OLD_SUPREMUM);
}
}
/****************************************************************
TRUE if the record is a user record on the page. */
UNIV_INLINE
ibool
page_rec_is_user_rec_low(
/*=====================*/
/* out: TRUE if a user record */
ulint offset) /* in: record offset on page */
{
ut_ad(offset >= PAGE_NEW_INFIMUM);
#if PAGE_OLD_INFIMUM < PAGE_NEW_INFIMUM
# error "PAGE_OLD_INFIMUM < PAGE_NEW_INFIMUM"
#endif
#if PAGE_OLD_SUPREMUM < PAGE_NEW_SUPREMUM
# error "PAGE_OLD_SUPREMUM < PAGE_NEW_SUPREMUM"
#endif
#if PAGE_NEW_INFIMUM > PAGE_OLD_SUPREMUM
# error "PAGE_NEW_INFIMUM > PAGE_OLD_SUPREMUM"
#endif
#if PAGE_OLD_INFIMUM > PAGE_NEW_SUPREMUM
# error "PAGE_OLD_INFIMUM > PAGE_NEW_SUPREMUM"
#endif
#if PAGE_NEW_SUPREMUM > PAGE_OLD_SUPREMUM_END
# error "PAGE_NEW_SUPREMUM > PAGE_OLD_SUPREMUM_END"
#endif
#if PAGE_OLD_SUPREMUM > PAGE_NEW_SUPREMUM_END
# error "PAGE_OLD_SUPREMUM > PAGE_NEW_SUPREMUM_END"
#endif
ut_ad(offset <= UNIV_PAGE_SIZE - PAGE_EMPTY_DIR_START);
return(UNIV_LIKELY(offset != PAGE_NEW_SUPREMUM)
&& UNIV_LIKELY(offset != PAGE_NEW_INFIMUM)
&& UNIV_LIKELY(offset != PAGE_OLD_INFIMUM)
&& UNIV_LIKELY(offset != PAGE_OLD_SUPREMUM));
}
/****************************************************************
TRUE if the record is the supremum record on a page. */
UNIV_INLINE
ibool
page_rec_is_supremum_low(
/*=====================*/
/* out: TRUE if the supremum record */
ulint offset) /* in: record offset on page */
{
ut_ad(offset >= PAGE_NEW_INFIMUM);
ut_ad(offset <= UNIV_PAGE_SIZE - PAGE_EMPTY_DIR_START);
return(UNIV_UNLIKELY(offset == PAGE_NEW_SUPREMUM)
|| UNIV_UNLIKELY(offset == PAGE_OLD_SUPREMUM));
}
/****************************************************************
TRUE if the record is the infimum record on a page. */
UNIV_INLINE
ibool
page_rec_is_infimum_low(
/*====================*/
/* out: TRUE if the infimum record */
ulint offset) /* in: record offset on page */
{
ut_ad(offset >= PAGE_NEW_INFIMUM);
ut_ad(offset <= UNIV_PAGE_SIZE - PAGE_EMPTY_DIR_START);
return(UNIV_UNLIKELY(offset == PAGE_NEW_INFIMUM)
|| UNIV_UNLIKELY(offset == PAGE_OLD_INFIMUM));
}
/****************************************************************
TRUE if the record is a user record on the page. */
UNIV_INLINE
ibool
page_rec_is_user_rec(
/*=================*/
/* out: TRUE if a user record */
const rec_t* rec) /* in: record */
{
return(page_rec_is_user_rec_low(page_offset(rec)));
}
/****************************************************************
TRUE if the record is the supremum record on a page. */
UNIV_INLINE
ibool
page_rec_is_supremum(
/*=================*/
/* out: TRUE if the supremum record */
const rec_t* rec) /* in: record */
{
return(page_rec_is_supremum_low(page_offset(rec)));
}
/****************************************************************
TRUE if the record is the infimum record on a page. */
UNIV_INLINE
ibool
page_rec_is_infimum(
/*================*/
/* out: TRUE if the infimum record */
const rec_t* rec) /* in: record */
{
return(page_rec_is_infimum_low(page_offset(rec)));
}
#ifndef UNIV_HOTBACKUP
/*****************************************************************
Compares a data tuple to a physical record. Differs from the function
cmp_dtuple_rec_with_match in the way that the record must reside on an
index page, and also page infimum and supremum records can be given in
the parameter rec. These are considered as the negative infinity and
the positive infinity in the alphabetical order. */
UNIV_INLINE
int
page_cmp_dtuple_rec_with_match(
/*===========================*/
/* out: 1, 0, -1, if dtuple is greater, equal,
less than rec, respectively, when only the
common first fields are compared */
const dtuple_t* dtuple, /* in: data tuple */
const rec_t* rec, /* in: physical record on a page; may also
be page infimum or supremum, in which case
matched-parameter values below are not
affected */
const ulint* offsets,/* in: array returned by rec_get_offsets() */
ulint* matched_fields, /* in/out: number of already completely
matched fields; when function returns
contains the value for current comparison */
ulint* matched_bytes) /* in/out: number of already matched
bytes within the first field not completely
matched; when function returns contains the
value for current comparison */
{
ulint rec_offset;
ut_ad(dtuple_check_typed(dtuple));
ut_ad(rec_offs_validate(rec, NULL, offsets));
ut_ad(!rec_offs_comp(offsets) == !page_rec_is_comp(rec));
rec_offset = page_offset(rec);
if (UNIV_UNLIKELY(rec_offset == PAGE_NEW_INFIMUM)
|| UNIV_UNLIKELY(rec_offset == PAGE_OLD_INFIMUM)) {
return(1);
}
if (UNIV_UNLIKELY(rec_offset == PAGE_NEW_SUPREMUM)
|| UNIV_UNLIKELY(rec_offset == PAGE_OLD_SUPREMUM)) {
return(-1);
}
return(cmp_dtuple_rec_with_match(dtuple, rec, offsets,
matched_fields,
matched_bytes));
}
#endif /* !UNIV_HOTBACKUP */
/*****************************************************************
Gets the page number. */
UNIV_INLINE
ulint
page_get_page_no(
/*=============*/
/* out: page number */
const page_t* page) /* in: page */
{
ut_ad(page == page_align((page_t*) page));
return(mach_read_from_4(page + FIL_PAGE_OFFSET));
}
/*****************************************************************
Gets the tablespace identifier. */
UNIV_INLINE
ulint
page_get_space_id(
/*==============*/
/* out: space id */
const page_t* page) /* in: page */
{
ut_ad(page == page_align((page_t*) page));
return(mach_read_from_4(page + FIL_PAGE_ARCH_LOG_NO_OR_SPACE_ID));
}
/*****************************************************************
Gets the number of user records on page (infimum and supremum records
are not user records). */
UNIV_INLINE
ulint
page_get_n_recs(
/*============*/
/* out: number of user records */
const page_t* page) /* in: index page */
{
return(page_header_get_field(page, PAGE_N_RECS));
}
/*****************************************************************
Gets the number of dir slots in directory. */
UNIV_INLINE
ulint
page_dir_get_n_slots(
/*=================*/
/* out: number of slots */
const page_t* page) /* in: index page */
{
return(page_header_get_field(page, PAGE_N_DIR_SLOTS));
}
/*****************************************************************
Sets the number of dir slots in directory. */
UNIV_INLINE
void
page_dir_set_n_slots(
/*=================*/
page_t* page, /* in/out: page */
page_zip_des_t* page_zip,/* in/out: compressed page whose
uncompressed part will be updated, or NULL */
ulint n_slots)/* in: number of slots */
{
page_header_set_field(page, page_zip, PAGE_N_DIR_SLOTS, n_slots);
}
/*****************************************************************
Gets the number of records in the heap. */
UNIV_INLINE
ulint
page_dir_get_n_heap(
/*================*/
/* out: number of user records */
const page_t* page) /* in: index page */
{
return(page_header_get_field(page, PAGE_N_HEAP) & 0x7fff);
}
/*****************************************************************
Sets the number of records in the heap. */
UNIV_INLINE
void
page_dir_set_n_heap(
/*================*/
page_t* page, /* in/out: index page */
page_zip_des_t* page_zip,/* in/out: compressed page whose
uncompressed part will be updated, or NULL.
Note that the size of the dense page directory
in the compressed page trailer is
n_heap * PAGE_ZIP_DIR_SLOT_SIZE. */
ulint n_heap) /* in: number of records */
{
ut_ad(n_heap < 0x8000);
ut_ad(!page_zip || n_heap
== (page_header_get_field(page, PAGE_N_HEAP) & 0x7fff) + 1);
page_header_set_field(page, page_zip, PAGE_N_HEAP, n_heap
| (0x8000
& page_header_get_field(page, PAGE_N_HEAP)));
}
#ifdef UNIV_DEBUG
/*****************************************************************
Gets pointer to nth directory slot. */
UNIV_INLINE
page_dir_slot_t*
page_dir_get_nth_slot(
/*==================*/
/* out: pointer to dir slot */
const page_t* page, /* in: index page */
ulint n) /* in: position */
{
ut_ad(page_dir_get_n_slots(page) > n);
return((page_dir_slot_t*)
page + UNIV_PAGE_SIZE - PAGE_DIR
- (n + 1) * PAGE_DIR_SLOT_SIZE);
}
#endif /* UNIV_DEBUG */
/******************************************************************
Used to check the consistency of a record on a page. */
UNIV_INLINE
ibool
page_rec_check(
/*===========*/
/* out: TRUE if succeed */
const rec_t* rec) /* in: record */
{
const page_t* page = page_align(rec);
ut_a(rec);
ut_a(page_offset(rec) <= page_header_get_field(page, PAGE_HEAP_TOP));
ut_a(page_offset(rec) >= PAGE_DATA);
return(TRUE);
}
/*******************************************************************
Gets the record pointed to by a directory slot. */
UNIV_INLINE
const rec_t*
page_dir_slot_get_rec(
/*==================*/
/* out: pointer to record */
const page_dir_slot_t* slot) /* in: directory slot */
{
return(page_align(slot) + mach_read_from_2(slot));
}
/*******************************************************************
This is used to set the record offset in a directory slot. */
UNIV_INLINE
void
page_dir_slot_set_rec(
/*==================*/
page_dir_slot_t* slot, /* in: directory slot */
rec_t* rec) /* in: record on the page */
{
ut_ad(page_rec_check(rec));
mach_write_to_2(slot, page_offset(rec));
}
/*******************************************************************
Gets the number of records owned by a directory slot. */
UNIV_INLINE
ulint
page_dir_slot_get_n_owned(
/*======================*/
/* out: number of records */
const page_dir_slot_t* slot) /* in: page directory slot */
{
const rec_t* rec = page_dir_slot_get_rec(slot);
if (page_rec_is_comp(slot)) {
return(rec_get_n_owned_new(rec));
} else {
return(rec_get_n_owned_old(rec));
}
}
/*******************************************************************
This is used to set the owned records field of a directory slot. */
UNIV_INLINE
void
page_dir_slot_set_n_owned(
/*======================*/
page_dir_slot_t*slot, /* in/out: directory slot */
page_zip_des_t* page_zip,/* in/out: compressed page, or NULL */
ulint n) /* in: number of records owned by the slot */
{
rec_t* rec = (rec_t*) page_dir_slot_get_rec(slot);
if (page_rec_is_comp(slot)) {
rec_set_n_owned_new(rec, page_zip, n);
} else {
ut_ad(!page_zip);
rec_set_n_owned_old(rec, n);
}
}
/****************************************************************
Calculates the space reserved for directory slots of a given number of
records. The exact value is a fraction number n * PAGE_DIR_SLOT_SIZE /
PAGE_DIR_SLOT_MIN_N_OWNED, and it is rounded upwards to an integer. */
UNIV_INLINE
ulint
page_dir_calc_reserved_space(
/*=========================*/
ulint n_recs) /* in: number of records */
{
return((PAGE_DIR_SLOT_SIZE * n_recs + PAGE_DIR_SLOT_MIN_N_OWNED - 1)
/ PAGE_DIR_SLOT_MIN_N_OWNED);
}
/****************************************************************
Gets the pointer to the next record on the page. */
UNIV_INLINE
const rec_t*
page_rec_get_next_low(
/*==================*/
/* out: pointer to next record */
const rec_t* rec, /* in: pointer to record */
ulint comp) /* in: nonzero=compact page layout */
{
ulint offs;
const page_t* page;
ut_ad(page_rec_check(rec));
page = page_align(rec);
offs = rec_get_next_offs(rec, comp);
if (UNIV_UNLIKELY(offs >= UNIV_PAGE_SIZE)) {
fprintf(stderr,
"InnoDB: Next record offset is nonsensical %lu"
" in record at offset %lu\n"
"InnoDB: rec address %p, space id %lu, page %lu\n",
(ulong)offs, (ulong) page_offset(rec),
(void*) rec,
(ulong) page_get_space_id(page),
(ulong) page_get_page_no(page));
buf_page_print(page, 0);
ut_error;
}
if (UNIV_UNLIKELY(offs == 0)) {
return(NULL);
}
return(page + offs);
}
/****************************************************************
Gets the pointer to the next record on the page. */
UNIV_INLINE
rec_t*
page_rec_get_next(
/*==============*/
/* out: pointer to next record */
rec_t* rec) /* in: pointer to record */
{
return((rec_t*) page_rec_get_next_low(rec, page_rec_is_comp(rec)));
}
/****************************************************************
Gets the pointer to the next record on the page. */
UNIV_INLINE
const rec_t*
page_rec_get_next_const(
/*====================*/
/* out: pointer to next record */
const rec_t* rec) /* in: pointer to record */
{
return(page_rec_get_next_low(rec, page_rec_is_comp(rec)));
}
/****************************************************************
Sets the pointer to the next record on the page. */
UNIV_INLINE
void
page_rec_set_next(
/*==============*/
rec_t* rec, /* in: pointer to record,
must not be page supremum */
rec_t* next) /* in: pointer to next record,
must not be page infimum */
{
ulint offs;
ut_ad(page_rec_check(rec));
ut_ad(!page_rec_is_supremum(rec));
ut_ad(rec != next);
ut_ad(!next || !page_rec_is_infimum(next));
ut_ad(!next || page_align(rec) == page_align(next));
if (UNIV_LIKELY(next != NULL)) {
offs = page_offset(next);
} else {
offs = 0;
}
if (page_rec_is_comp(rec)) {
rec_set_next_offs_new(rec, offs);
} else {
rec_set_next_offs_old(rec, offs);
}
}
/****************************************************************
Gets the pointer to the previous record. */
UNIV_INLINE
const rec_t*
page_rec_get_prev_const(
/*====================*/
/* out: pointer to previous record */
const rec_t* rec) /* in: pointer to record, must not be page
infimum */
{
const page_dir_slot_t* slot;
ulint slot_no;
const rec_t* rec2;
const rec_t* prev_rec = NULL;
const page_t* page;
ut_ad(page_rec_check(rec));
page = page_align(rec);
ut_ad(!page_rec_is_infimum(rec));
slot_no = page_dir_find_owner_slot(rec);
ut_a(slot_no != 0);
slot = page_dir_get_nth_slot(page, slot_no - 1);
rec2 = page_dir_slot_get_rec(slot);
if (page_is_comp(page)) {
while (rec != rec2) {
prev_rec = rec2;
rec2 = page_rec_get_next_low(rec2, TRUE);
}
} else {
while (rec != rec2) {
prev_rec = rec2;
rec2 = page_rec_get_next_low(rec2, FALSE);
}
}
ut_a(prev_rec);
return(prev_rec);
}
/****************************************************************
Gets the pointer to the previous record. */
UNIV_INLINE
rec_t*
page_rec_get_prev(
/*==============*/
/* out: pointer to previous record */
rec_t* rec) /* in: pointer to record, must not be page
infimum */
{
return((rec_t*) page_rec_get_prev_const(rec));
}
/*******************************************************************
Looks for the record which owns the given record. */
UNIV_INLINE
rec_t*
page_rec_find_owner_rec(
/*====================*/
/* out: the owner record */
rec_t* rec) /* in: the physical record */
{
ut_ad(page_rec_check(rec));
if (page_rec_is_comp(rec)) {
while (rec_get_n_owned_new(rec) == 0) {
rec = page_rec_get_next(rec);
}
} else {
while (rec_get_n_owned_old(rec) == 0) {
rec = page_rec_get_next(rec);
}
}
return(rec);
}
/**************************************************************
Returns the base extra size of a physical record. This is the
size of the fixed header, independent of the record size. */
UNIV_INLINE
ulint
page_rec_get_base_extra_size(
/*=========================*/
/* out: REC_N_NEW_EXTRA_BYTES
or REC_N_OLD_EXTRA_BYTES */
const rec_t* rec) /* in: physical record */
{
#if REC_N_NEW_EXTRA_BYTES + 1 != REC_N_OLD_EXTRA_BYTES
# error "REC_N_NEW_EXTRA_BYTES + 1 != REC_N_OLD_EXTRA_BYTES"
#endif
return(REC_N_NEW_EXTRA_BYTES + (ulint) !page_rec_is_comp(rec));
}
/****************************************************************
Returns the sum of the sizes of the records in the record list, excluding
the infimum and supremum records. */
UNIV_INLINE
ulint
page_get_data_size(
/*===============*/
/* out: data in bytes */
const page_t* page) /* in: index page */
{
ulint ret;
ret = (ulint)(page_header_get_field(page, PAGE_HEAP_TOP)
- (page_is_comp(page)
? PAGE_NEW_SUPREMUM_END
: PAGE_OLD_SUPREMUM_END)
- page_header_get_field(page, PAGE_GARBAGE));
ut_ad(ret < UNIV_PAGE_SIZE);
return(ret);
}
/****************************************************************
Allocates a block of memory from the free list of an index page. */
UNIV_INTERN
void
page_mem_alloc_free(
/*================*/
page_t* page, /* in/out: index page */
page_zip_des_t* page_zip,/* in/out: compressed page with enough
space available for inserting the record,
or NULL */
rec_t* next_rec,/* in: pointer to the new head of the
free record list */
ulint need) /* in: number of bytes allocated */
{
ulint garbage;
#ifdef UNIV_DEBUG
const rec_t* old_rec = page_header_get_ptr(page, PAGE_FREE);
ulint next_offs;
ut_ad(old_rec);
next_offs = rec_get_next_offs(old_rec, page_is_comp(page));
ut_ad(next_rec == (next_offs ? page + next_offs : NULL));
#endif
page_header_set_ptr(page, page_zip, PAGE_FREE, next_rec);
garbage = page_header_get_field(page, PAGE_GARBAGE);
ut_ad(garbage >= need);
page_header_set_field(page, page_zip, PAGE_GARBAGE, garbage - need);
}
/*****************************************************************
Calculates free space if a page is emptied. */
UNIV_INLINE
ulint
page_get_free_space_of_empty(
/*=========================*/
/* out: free space */
ulint comp) /* in: nonzero=compact page layout */
{
if (UNIV_LIKELY(comp)) {
return((ulint)(UNIV_PAGE_SIZE
- PAGE_NEW_SUPREMUM_END
- PAGE_DIR
- 2 * PAGE_DIR_SLOT_SIZE));
}
return((ulint)(UNIV_PAGE_SIZE
- PAGE_OLD_SUPREMUM_END
- PAGE_DIR
- 2 * PAGE_DIR_SLOT_SIZE));
}
/****************************************************************
Each user record on a page, and also the deleted user records in the heap
takes its size plus the fraction of the dir cell size /
PAGE_DIR_SLOT_MIN_N_OWNED bytes for it. If the sum of these exceeds the
value of page_get_free_space_of_empty, the insert is impossible, otherwise
it is allowed. This function returns the maximum combined size of records
which can be inserted on top of the record heap. */
UNIV_INLINE
ulint
page_get_max_insert_size(
/*=====================*/
/* out: maximum combined size for
inserted records */
const page_t* page, /* in: index page */
ulint n_recs) /* in: number of records */
{
ulint occupied;
ulint free_space;
if (page_is_comp(page)) {
occupied = page_header_get_field(page, PAGE_HEAP_TOP)
- PAGE_NEW_SUPREMUM_END
+ page_dir_calc_reserved_space(
n_recs + page_dir_get_n_heap(page) - 2);
free_space = page_get_free_space_of_empty(TRUE);
} else {
occupied = page_header_get_field(page, PAGE_HEAP_TOP)
- PAGE_OLD_SUPREMUM_END
+ page_dir_calc_reserved_space(
n_recs + page_dir_get_n_heap(page) - 2);
free_space = page_get_free_space_of_empty(FALSE);
}
/* Above the 'n_recs +' part reserves directory space for the new
inserted records; the '- 2' excludes page infimum and supremum
records */
if (occupied > free_space) {
return(0);
}
return(free_space - occupied);
}
/****************************************************************
Returns the maximum combined size of records which can be inserted on top
of the record heap if a page is first reorganized. */
UNIV_INLINE
ulint
page_get_max_insert_size_after_reorganize(
/*======================================*/
/* out: maximum combined size for
inserted records */
const page_t* page, /* in: index page */
ulint n_recs) /* in: number of records */
{
ulint occupied;
ulint free_space;
occupied = page_get_data_size(page)
+ page_dir_calc_reserved_space(n_recs + page_get_n_recs(page));
free_space = page_get_free_space_of_empty(page_is_comp(page));
if (occupied > free_space) {
return(0);
}
return(free_space - occupied);
}
/****************************************************************
Puts a record to free list. */
UNIV_INLINE
void
page_mem_free(
/*==========*/
page_t* page, /* in/out: index page */
page_zip_des_t* page_zip,/* in/out: compressed page, or NULL */
rec_t* rec, /* in: pointer to the (origin of) record */
dict_index_t* index, /* in: index of rec */
const ulint* offsets)/* in: array returned by rec_get_offsets() */
{
rec_t* free;
ulint garbage;
ut_ad(rec_offs_validate(rec, index, offsets));
free = page_header_get_ptr(page, PAGE_FREE);
page_rec_set_next(rec, free);
page_header_set_ptr(page, page_zip, PAGE_FREE, rec);
garbage = page_header_get_field(page, PAGE_GARBAGE);
page_header_set_field(page, page_zip, PAGE_GARBAGE,
garbage + rec_offs_size(offsets));
if (UNIV_LIKELY_NULL(page_zip)) {
page_zip_dir_delete(page_zip, rec, index, offsets, free);
} else {
page_header_set_field(page, page_zip, PAGE_N_RECS,
page_get_n_recs(page) - 1);
}
}
#ifdef UNIV_MATERIALIZE
#undef UNIV_INLINE
#define UNIV_INLINE UNIV_INLINE_ORIGINAL
#endif