Commit e2513bf0 authored by unknown's avatar unknown

Apply snapshot innodb-5.1-ss1989

Fixes the following bugs:

Bug #30706: SQL thread on slave is allowed to block client queries when slave load is high
  Add (innodb|innobase|srv)_replication_delay MySQL config parameter.

Bug #30888: Innodb table + stored procedure + row deletion = server crash
  While adding code for the low level read of the AUTOINC value from the index,
  the case for MEDIUM ints which are 3 bytes was missed triggering an
  assertion.

Bug #30907: Regression: "--innodb_autoinc_lock_mode=0" (off) not same as older releases
  We don't rely on *first_value to be 0 when checking whether
  get_auto_increment() has been invoked for the first time in a multi-row
  INSERT. We instead use trx_t::n_autoinc_rows. Initialize trx::n_autoinc_rows
  inside ha_innobase::start_stmt() too.

Bug #31444: "InnoDB: Error: MySQL is freeing a thd" in innodb_mysql.test
  ha_innobase::external_lock(): Update prebuilt->mysql_has_locked and
  trx->n_mysql_tables_in_use only after row_lock_table_for_mysql() returns
  DB_SUCCESS.  A timeout on LOCK TABLES would lead to an inconsistent state,
  which would cause trx_free() to print a warning.

Bug #31494: innodb + 5.1 + read committed crash, assertion
  Set an error code when a deadlock occurs in semi-consistent read.


mysql-test/r/innodb.result:
  Apply snapshot innodb-5.1-ss1989
  
  Also, a test is moved into the new innodb_autoinc_lock_mode_zero
  test, because it depends on a non-default setting for a read-only
  variable.
  
  Revision r1821:
  Merge a change from MySQL AB:
  
  ChangeSet@1.2536.50.1  2007-08-02 12:45:56-07:00  igor@mysql.com
  
  Fixed bug#28404.
  This patch adds cost estimation for the queries with ORDER BY / GROUP BY
  and LIMIT.
  If there was a ref/range access to the table whose rows were required
  to be ordered in the result set the optimizer always employed this access
  though a scan by a different index that was compatible with the required
  order could be cheaper to produce the first L rows of the result set.
  Now for such queries the optimizer makes a choice between the cheapest
  ref/range accesses not compatible with the given order and index scans
  compatible with it.
  
  innodb.result: Adjusted results for test cases affected fy the fix for
  bug #28404.
  
  
  Revision r1781:
  Fix a test case that was broken after Bug#16979 fix. See r1645 and r1735.
  The variable used in the tests below was introduced in r1735.
  
  
  Revision r1792:
  innodb.result: Revert r1655, which should have been reverted as part of r1781.
  
  
  Revision r1843:
  Add test for Bug# 21409, the actual bug was fixed in r1334.
mysql-test/t/innodb.test:
  Apply snapshot innodb-5.1-ss1989
  
  Also, a test is moved into the new innodb_autoinc_lock_mode_zero
  test, because it depends on a non-default setting for a read-only
  variable.
  
  Revision r1781:
  Fix a test case that was broken after Bug#16979 fix. See r1645 and r1735.
  The variable used in the tests below was introduced in r1735.
  
  
  Revision r1843:
  Add test for Bug# 21409, the actual bug was fixed in r1334.
storage/innobase/buf/buf0lru.c:
  Apply snapshot innodb-5.1-ss1989
  
  Revision r1819:
  Merge r1815:1817 from branches/zip: Improve Valgrind instrumentation.
  
  UNIV_MEM_ASSERT_RW(): New macro, to check that the contents of a memory
  area is defined.
  
  UNIV_MEM_ASSERT_W(): New macro, to check that a memory area is writable.
  
  UNIV_MEM_ASSERT_AND_FREE(): New macro, to check that the memory is
  writable before declaring it free (unwritable).  This replaces UNIV_MEM_FREE()
  in many places.
  
  mem_init_buf(): Check that the memory is writable, and declare it undefined.
  
  mem_erase_buf(): Check that the memory is writable, and declare it freed.
storage/innobase/dict/dict0dict.c:
  Apply snapshot innodb-5.1-ss1989
  
  Revision r1894:
  Add debug lock checks to autoinc functions. Add lock guards around an
  invocation of dict_table_autoinc_initialize().
storage/innobase/dict/dict0load.c:
  Apply snapshot innodb-5.1-ss1989
  
  Revision r1974:
  Prevent loading of tables that have unsupported features most notably
  FTS indexes.
storage/innobase/handler/ha_innodb.cc:
  Apply snapshot innodb-5.1-ss1989
  
  Revision r1850:
  Implement this feature request:
  http://bugs.mysql.com/30706
  
  * Add a function that returns the number of microseconds since
    epoch - ut_time_us().
  
  * Add (innodb|innobase|srv)_replication_delay MySQL config parameter.
  
  * Add UT_WAIT_FOR() macro that waits for a specified condition to occur
    until a timeout elapses.
  
  * Using all of the above, handle the replication thread specially in
    srv_conc_enter_innodb().
  
  Approved by:	Heikki
  
  
  
  Revision r1887:
  Merge changes from MySQL AB:
  
  ChangeSet@1.2528.115.25  2007-08-27 18:18:14-06:00  tsmith@hindu.god
  
  Fix some Windows compiler warnings.
  
  dict0mem.c: Fix compiler warning with a cast.
  
  ha_innodb.cc: Change type to fix a compiler warning.
  
  
  Revision r1809:
  ha_innobase::external_lock(): Update prebuilt->mysql_has_locked and
  trx->n_mysql_tables_in_use only after row_lock_table_for_mysql()
  returns DB_SUCCESS.  A timeout on LOCK TABLES would lead to an
  inconsistent state, which would cause trx_free() to print a warning.
  
  This was later reported as Bug #31444.
  
  
  Revision r1833:
  Add /*== ... === */ decoration that was missing around some auto-inc functions.
  Add a missing comment, fix the length of a decoration.  Initialize the *value
  out parameter in ha_innobase::innobase_get_auto_increment().
  
  
  Revision r1866:
  Revert r1850 as MySQL did not approve the addition.
  
  log for r1850:
  
  Implement this feature request:
  http://bugs.mysql.com/30706
  
  * Add a function that returns the number of microseconds since
    epoch - ut_time_us().
  
  * Add (innodb|innobase|srv)_replication_delay MySQL config parameter.
  
  * Add UT_WAIT_FOR() macro that waits for a specified condition to occur
    until a timeout elapses.
  
  * Using all of the above, handle the replication thread specially in
    srv_conc_enter_innodb().
  
  
  Revision r1846:
  Add config option innodb_use_adaptive_hash_indexes to enable/disable
  adaptive hash indexes. It is enabled by default (no change in default
  behavior).
  
  Approved by:	Marko
  
  
  Revision r1974:
  Prevent loading of tables that have unsupported features most notably
  FTS indexes.
  
  
  Revision r1829:
  Add assertion to enforce check of an implicit invariant and add comment about
  retry of autoinc read semantics. We always reread the table's autoinc counter
  after attempting to initialize it i.e., we want to guarantee that a read of
  autoinc valus that is returned to the caller is always covered by the
  AUTOINC locking mechanism.
  
  
  Revision r1787:
  Move the prototype of innobase_print_identifier() from ut0ut.c to
  ha_prototypes.h.  Enclose the definitions in ha_prototypes.h in
  #ifndef UNIV_HOTBACKUP.
  
  
  Revision r1888:
  Merge a change from MySQL AB:
  
  ChangeSet@1.2528.115.30  2007-08-28 10:17:15-06:00  tsmith@hindu.god
  
  Fix another compiler warning on Windows in InnoDB.
  
  ha_innodb.cc:
  
  Fix compiler warning: ::get_auto_increment takes a ulonglong
  for nb_desired_values, but InnoDB's trx struct stores it as
  a ulint (unsigned long).  Probably harmless, as a single
  statement won't be asking for more than 2^32 rows.
  
  
  Revision r1987:
  Bug fix: The problem was that when write_row() attempted to update the max
  autoinc value, and if it was rolled back because of a deadlock, the 
  deadlock error (transaction rollback) was not being propagated back to MySQL.
  
  
  Revision r1889:
  Merge a change from MySQL AB:
  
  ChangeSet@1.2560  2007-09-21 10:15:16+02:00  gkodinov@local
  
  ha_innodb.cc: fixed type conversion warnings revealed by bug 30639 
  
  
  Revision r1989:
  Suppress printing of deadlock errors while reading the autoinc value.
  DB_DEADLOCK errors are part of normal processing and excessive printing
  of these error messages could be disconcerting for users. 
  
  
  Revision r1828:
  Fix two bugs:
  
  Bug# 30907: We don't rely on *first_value to be 0 when checking whether
  get_auto_increment() has been invoked for the first time in a multi-row
  INSERT. We instead use trx_t::n_autoinc_rows. Initialize trx::n_autoinc_rows
  inside ha_innobase::start_stmt() too.
  
  Bug# 30888: While adding code for the low level read of the AUTOINC value
  from the index, the case for MEDIUM ints which are 3 bytes was missed
  triggering an assertion.
storage/innobase/handler/ha_innodb.h:
  Apply snapshot innodb-5.1-ss1989
  
  Revision r1844:
  Remove the prototypes of some functions inside #if 0.
  The function definitions were removed in r1746.
storage/innobase/ibuf/ibuf0ibuf.c:
  Apply snapshot innodb-5.1-ss1989
  
  Revision r1965:
  ibuf_insert_to_index_page(): Fix typos in diagnostic output.
storage/innobase/include/db0err.h:
  Apply snapshot innodb-5.1-ss1989
  
  Revision r1974:
  Prevent loading of tables that have unsupported features most notably
  FTS indexes.
storage/innobase/include/ha_prototypes.h:
  Apply snapshot innodb-5.1-ss1989
  
  Revision r1787:
  Move the prototype of innobase_print_identifier() from ut0ut.c to
  ha_prototypes.h.  Enclose the definitions in ha_prototypes.h in
  #ifndef UNIV_HOTBACKUP.
storage/innobase/include/mach0data.h:
  Apply snapshot innodb-5.1-ss1989
  
  Revision r1779:
  Fix a bug that handles the case where the host specific byte order matches
  the InnoDB storage byte order, which is big-endian.
storage/innobase/include/mach0data.ic:
  Apply snapshot innodb-5.1-ss1989
  
  Revision r1779:
  Fix a bug that handles the case where the host specific byte order matches
  the InnoDB storage byte order, which is big-endian.
storage/innobase/include/mem0dbg.h:
  Apply snapshot innodb-5.1-ss1989
  
  Revision r1830:
  Improve memory debugging.  This is follow-up to r1819.
  
  mem_heap_validate(): Compile this function also if UNIV_MEM_DEBUG is
  defined.  Previously, this function was only compiled with UNIV_DEBUG.
  
  mem_heap_free_heap_top(): Flag the memory allocated, not freed, for
  Valgrind.  Otherwise, Valgrind would complain on the second call of
  mem_heap_empty().
  
  UNIV_MEM_ASSERT_RW(), UNIV_MEM_ASSERT_W(): Display additional diagnostics
  for failed Valgrind checks.
storage/innobase/include/mem0mem.ic:
  Apply snapshot innodb-5.1-ss1989
  
  Revision r1830:
  Improve memory debugging.  This is follow-up to r1819.
  
  mem_heap_validate(): Compile this function also if UNIV_MEM_DEBUG is
  defined.  Previously, this function was only compiled with UNIV_DEBUG.
  
  mem_heap_free_heap_top(): Flag the memory allocated, not freed, for
  Valgrind.  Otherwise, Valgrind would complain on the second call of
  mem_heap_empty().
  
  UNIV_MEM_ASSERT_RW(), UNIV_MEM_ASSERT_W(): Display additional diagnostics
  for failed Valgrind checks.
  
  
  Revision r1937:
  mem_heap_free_top(): Remove a bogus Valgrind warning.
  
  
  Revision r1819:
  Merge r1815:1817 from branches/zip: Improve Valgrind instrumentation.
  
  UNIV_MEM_ASSERT_RW(): New macro, to check that the contents of a memory
  area is defined.
  
  UNIV_MEM_ASSERT_W(): New macro, to check that a memory area is writable.
  
  UNIV_MEM_ASSERT_AND_FREE(): New macro, to check that the memory is
  writable before declaring it free (unwritable).  This replaces UNIV_MEM_FREE()
  in many places.
  
  mem_init_buf(): Check that the memory is writable, and declare it undefined.
  
  mem_erase_buf(): Check that the memory is writable, and declare it freed.
storage/innobase/include/rem0rec.ic:
  Apply snapshot innodb-5.1-ss1989
  
  Revision r1918:
  Improve Valgrind instrumentation.
  
  rec_offs_set_n_alloc(): Use UNIV_MEM_ASSERT_AND_ALLOC().
  
  UNIV_MEM_ASSERT_AND_ALLOC(): New directive, similar to
  UNIV_MEM_ASSERT_AND_FREE().
storage/innobase/include/row0mysql.h:
  Apply snapshot innodb-5.1-ss1989
  
  Revision r1783:
  Correct the function comments of row_create_table_for_mysql() and
  row_drop_table_for_mysql().
storage/innobase/include/sync0rw.h:
  Apply snapshot innodb-5.1-ss1989
  
  Revision r1757:
  Enclose rw_lock_validate() in #ifdef UNIV_DEBUG.  It is only called by
  debug assertions.
storage/innobase/include/univ.i:
  Apply snapshot innodb-5.1-ss1989
  
  Revision r1827:
  Merge r1826 from branches/zip: UNIV_MEM_ASSERT_AND_FREE():
  Use UNIV_MEM_ASSERT_W() instead of UNIV_MEM_ASSERT_RW().
  The memory area need not be initialized.
  This mistake was made in r1815.
  
  
  Revision r1918:
  Improve Valgrind instrumentation.
  
  rec_offs_set_n_alloc(): Use UNIV_MEM_ASSERT_AND_ALLOC().
  
  UNIV_MEM_ASSERT_AND_ALLOC(): New directive, similar to
  UNIV_MEM_ASSERT_AND_FREE().
  
  
  Revision r1830:
  Improve memory debugging.  This is follow-up to r1819.
  
  mem_heap_validate(): Compile this function also if UNIV_MEM_DEBUG is
  defined.  Previously, this function was only compiled with UNIV_DEBUG.
  
  mem_heap_free_heap_top(): Flag the memory allocated, not freed, for
  Valgrind.  Otherwise, Valgrind would complain on the second call of
  mem_heap_empty().
  
  UNIV_MEM_ASSERT_RW(), UNIV_MEM_ASSERT_W(): Display additional diagnostics
  for failed Valgrind checks.
  
  
  Revision r1819:
  Merge r1815:1817 from branches/zip: Improve Valgrind instrumentation.
  
  UNIV_MEM_ASSERT_RW(): New macro, to check that the contents of a memory
  area is defined.
  
  UNIV_MEM_ASSERT_W(): New macro, to check that a memory area is writable.
  
  UNIV_MEM_ASSERT_AND_FREE(): New macro, to check that the memory is
  writable before declaring it free (unwritable).  This replaces UNIV_MEM_FREE()
  in many places.
  
  mem_init_buf(): Check that the memory is writable, and declare it undefined.
  
  mem_erase_buf(): Check that the memory is writable, and declare it freed.
  
  
  Revision r1948:
  UNIV_MEM_ASSERT_RW(), UNIV_MEM_ASSERT_W(): Display also __FILE__ and __LINE__
  when these Valgrind checks fail.
storage/innobase/include/ut0ut.h:
  Apply snapshot innodb-5.1-ss1989
  
  Revision r1850:
  Implement this feature request:
  http://bugs.mysql.com/30706
  
  * Add a function that returns the number of microseconds since
    epoch - ut_time_us().
  
  * Add (innodb|innobase|srv)_replication_delay MySQL config parameter.
  
  * Add UT_WAIT_FOR() macro that waits for a specified condition to occur
    until a timeout elapses.
  
  * Using all of the above, handle the replication thread specially in
    srv_conc_enter_innodb().
  
  Approved by:	Heikki
  
  
  
  Revision r1862:
  Add ut_snprintf() function. On Windows this needs to be implemented
  using auxiliary functions because there is no snprintf-variant on
  Windows that behaves exactly as specified in the standard:
  
  * Always return the number of characters that would have been printed
    if the size were unlimited (not including the final `\0').
  * Always '\0'-terminate the result
  * Do not touch the buffer if size=0, only return the number of characters
    that would have been printed. Can be used to estimate the size needed
    and to allocate it dynamically.
  
  See http://www.freebsd.org/cgi/query-pr.cgi?pr=87260 for the reason why
  2 ap variables are used.
  
  Approved by:	Heikki
  
  
  Revision r1866:
  Revert r1850 as MySQL did not approve the addition.
  
  log for r1850:
  
  Implement this feature request:
  http://bugs.mysql.com/30706
  
  * Add a function that returns the number of microseconds since
    epoch - ut_time_us().
  
  * Add (innodb|innobase|srv)_replication_delay MySQL config parameter.
  
  * Add UT_WAIT_FOR() macro that waits for a specified condition to occur
    until a timeout elapses.
  
  * Using all of the above, handle the replication thread specially in
    srv_conc_enter_innodb().
storage/innobase/mem/mem0dbg.c:
  Apply snapshot innodb-5.1-ss1989
  
  Revision r1830:
  Improve memory debugging.  This is follow-up to r1819.
  
  mem_heap_validate(): Compile this function also if UNIV_MEM_DEBUG is
  defined.  Previously, this function was only compiled with UNIV_DEBUG.
  
  mem_heap_free_heap_top(): Flag the memory allocated, not freed, for
  Valgrind.  Otherwise, Valgrind would complain on the second call of
  mem_heap_empty().
  
  UNIV_MEM_ASSERT_RW(), UNIV_MEM_ASSERT_W(): Display additional diagnostics
  for failed Valgrind checks.
  
  
  Revision r1819:
  Merge r1815:1817 from branches/zip: Improve Valgrind instrumentation.
  
  UNIV_MEM_ASSERT_RW(): New macro, to check that the contents of a memory
  area is defined.
  
  UNIV_MEM_ASSERT_W(): New macro, to check that a memory area is writable.
  
  UNIV_MEM_ASSERT_AND_FREE(): New macro, to check that the memory is
  writable before declaring it free (unwritable).  This replaces UNIV_MEM_FREE()
  in many places.
  
  mem_init_buf(): Check that the memory is writable, and declare it undefined.
  
  mem_erase_buf(): Check that the memory is writable, and declare it freed.
storage/innobase/mem/mem0mem.c:
  Apply snapshot innodb-5.1-ss1989
  
  Revision r1819:
  Merge r1815:1817 from branches/zip: Improve Valgrind instrumentation.
  
  UNIV_MEM_ASSERT_RW(): New macro, to check that the contents of a memory
  area is defined.
  
  UNIV_MEM_ASSERT_W(): New macro, to check that a memory area is writable.
  
  UNIV_MEM_ASSERT_AND_FREE(): New macro, to check that the memory is
  writable before declaring it free (unwritable).  This replaces UNIV_MEM_FREE()
  in many places.
  
  mem_init_buf(): Check that the memory is writable, and declare it undefined.
  
  mem_erase_buf(): Check that the memory is writable, and declare it freed.
storage/innobase/row/row0mysql.c:
  Apply snapshot innodb-5.1-ss1989
  
  Revision r1786:
  row_create_table_for_mysql(), row_truncate_table_for_mysql(),
  row_drop_table_for_mysql(): Do not mention innodb_force_recovery
  when newraw is set.
  
  
  Revision r1790:
  row_drop_table_for_mysql(): Before calling
  dict_table_remove_from_cache(table) and thus freeing the memory
  allocated for the table, copy the table name.  This avoids reading
  freed memory when name == table->name.
  
  Approved by Sunny.
  
  
  Revision r1783:
  Correct the function comments of row_create_table_for_mysql() and
  row_drop_table_for_mysql().
  
  
  Revision r1894:
  Add debug lock checks to autoinc functions. Add lock guards around an
  invocation of dict_table_autoinc_initialize().
storage/innobase/row/row0sel.c:
  Apply snapshot innodb-5.1-ss1989
  
  Revision r1782:
  Add comment that the variable dest should be word aligned. After discussion
  on IM with Heikki.
  
  
  Revision r1988:
  Set an error code when a deadlock occurs in semi-consistent read.  (Bug #31494)
  
  innodb-semi-consistent: New tests for InnoDB semi-consistent reads.
  Unfortunately, these will not trigger Bug #31494, because there merely
  occur lock wait timeouts, not deadlocks.
  
  
  Revision r1820:
  Use the clustered index and not the one selected by the optimizer in the plan,
  when building a previous version of the row. This bug is triggered when
  running queries via InnoDB's internal SQL parser; when InnoDB's optimizer
  selects a secondary index for the plan.
  
  
  Revision r1828:
  Fix two bugs:
  
  Bug# 30907: We don't rely on *first_value to be 0 when checking whether
  get_auto_increment() has been invoked for the first time in a multi-row
  INSERT. We instead use trx_t::n_autoinc_rows. Initialize trx::n_autoinc_rows
  inside ha_innobase::start_stmt() too.
  
  Bug# 30888: While adding code for the low level read of the AUTOINC value
  from the index, the case for MEDIUM ints which are 3 bytes was missed
  triggering an assertion.
  
  
  Revision r1779:
  Fix a bug that handles the case where the host specific byte order matches
  the InnoDB storage byte order, which is big-endian.
storage/innobase/sync/sync0rw.c:
  Apply snapshot innodb-5.1-ss1989
  
  Revision r1757:
  Enclose rw_lock_validate() in #ifdef UNIV_DEBUG.  It is only called by
  debug assertions.
storage/innobase/ut/ut0ut.c:
  Apply snapshot innodb-5.1-ss1989
  
  Revision r1850:
  Implement this feature request:
  http://bugs.mysql.com/30706
  
  * Add a function that returns the number of microseconds since
    epoch - ut_time_us().
  
  * Add (innodb|innobase|srv)_replication_delay MySQL config parameter.
  
  * Add UT_WAIT_FOR() macro that waits for a specified condition to occur
    until a timeout elapses.
  
  * Using all of the above, handle the replication thread specially in
    srv_conc_enter_innodb().
  
  Approved by:	Heikki
  
  
  
  Revision r1873:
  snprintf() should always return non-negative result. According to
  Microsoft documentation about _vscprintf():
  
    If format is a null pointer, the invalid parameter handler is invoked,
    as described in Parameter Validation. If execution is allowed to
    continue, the functions return -1 and set errno to EINVAL.
  
  The UNIX variant of snprintf() segfaults if format is a NULL pointer
  (similar to strlen(NULL) for example), so it is better to conform to
  this behavior and crash our custom Windows version instead of
  returning -1. Noone would expect -1 to be returned from snprintf().
  
  Cosmetic: Add a space after typecast.
  
  Approved by:	Marko
  
  
  Revision r1862:
  Add ut_snprintf() function. On Windows this needs to be implemented
  using auxiliary functions because there is no snprintf-variant on
  Windows that behaves exactly as specified in the standard:
  
  * Always return the number of characters that would have been printed
    if the size were unlimited (not including the final `\0').
  * Always '\0'-terminate the result
  * Do not touch the buffer if size=0, only return the number of characters
    that would have been printed. Can be used to estimate the size needed
    and to allocate it dynamically.
  
  See http://www.freebsd.org/cgi/query-pr.cgi?pr=87260 for the reason why
  2 ap variables are used.
  
  Approved by:	Heikki
  
  
  Revision r1866:
  Revert r1850 as MySQL did not approve the addition.
  
  log for r1850:
  
  Implement this feature request:
  http://bugs.mysql.com/30706
  
  * Add a function that returns the number of microseconds since
    epoch - ut_time_us().
  
  * Add (innodb|innobase|srv)_replication_delay MySQL config parameter.
  
  * Add UT_WAIT_FOR() macro that waits for a specified condition to occur
    until a timeout elapses.
  
  * Using all of the above, handle the replication thread specially in
    srv_conc_enter_innodb().
  
  
  Revision r1787:
  Move the prototype of innobase_print_identifier() from ut0ut.c to
  ha_prototypes.h.  Enclose the definitions in ha_prototypes.h in
  #ifndef UNIV_HOTBACKUP.
  
  
  Revision r1789:
  ut_print_namel(): Do not assume that all '/' are separators between
  database and table names.
  
  Approved by Heikki.
  
  
  Revision r1936:
  ut_print_buf(): Add a Valgrind check that the buffer is wholly defined.
mysql-test/r/innodb-semi-consistent.result:
  Apply snapshot innodb-5.1-ss1989
  
  
  Revision r1988:
  Set an error code when a deadlock occurs in semi-consistent read.  (Bug #31494)
  
  innodb-semi-consistent: New tests for InnoDB semi-consistent reads.
  Unfortunately, these will not trigger Bug #31494, because there merely
  occur lock wait timeouts, not deadlocks.
mysql-test/r/innodb_autoinc_lock_mode_zero.result:
  New test, using read-only setting --innodb-autoinc-lock-mode=0
mysql-test/t/innodb-semi-consistent-master.opt:
  Apply snapshot innodb-5.1-ss1989
  
  
  Revision r1988:
  Set an error code when a deadlock occurs in semi-consistent read.  (Bug #31494)
  
  innodb-semi-consistent: New tests for InnoDB semi-consistent reads.
  Unfortunately, these will not trigger Bug #31494, because there merely
  occur lock wait timeouts, not deadlocks.
mysql-test/t/innodb-semi-consistent.test:
  Apply snapshot innodb-5.1-ss1989
  
  
  Revision r1988:
  Set an error code when a deadlock occurs in semi-consistent read.  (Bug #31494)
  
  innodb-semi-consistent: New tests for InnoDB semi-consistent reads.
  Unfortunately, these will not trigger Bug #31494, because there merely
  occur lock wait timeouts, not deadlocks.
mysql-test/t/innodb_autoinc_lock_mode_zero-master.opt:
  New test, using read-only setting --innodb-autoinc-lock-mode=0
mysql-test/t/innodb_autoinc_lock_mode_zero.test:
  New test, using read-only setting --innodb-autoinc-lock-mode=0
parent 4cc5d3c1
set session transaction isolation level read committed;
create table t1(a int not null) engine=innodb DEFAULT CHARSET=latin1;
insert into t1 values (1),(2),(3),(4),(5),(6),(7);
set autocommit=0;
select * from t1 where a=3 lock in share mode;
a
3
set session transaction isolation level read committed;
set autocommit=0;
update t1 set a=10 where a=5;
ERROR HY000: Lock wait timeout exceeded; try restarting transaction
commit;
update t1 set a=10 where a=5;
select * from t1 where a=2 for update;
ERROR HY000: Lock wait timeout exceeded; try restarting transaction
select * from t1 where a=2 limit 1 for update;
a
2
update t1 set a=11 where a=6;
update t1 set a=12 where a=2;
ERROR HY000: Lock wait timeout exceeded; try restarting transaction
update t1 set a=13 where a=1;
ERROR HY000: Lock wait timeout exceeded; try restarting transaction
commit;
update t1 set a=14 where a=1;
commit;
select * from t1;
a
14
2
3
4
10
11
7
drop table t1;
...@@ -472,43 +472,6 @@ a b ...@@ -472,43 +472,6 @@ a b
3 3 3 3
drop table t1,t2; drop table t1,t2;
CREATE TABLE t1 ( CREATE TABLE t1 (
id int(11) NOT NULL auto_increment,
ggid varchar(32) binary DEFAULT '' NOT NULL,
email varchar(64) DEFAULT '' NOT NULL,
passwd varchar(32) binary DEFAULT '' NOT NULL,
PRIMARY KEY (id),
UNIQUE ggid (ggid)
) ENGINE=innodb;
insert into t1 (ggid,passwd) values ('test1','xxx');
insert into t1 (ggid,passwd) values ('test2','yyy');
insert into t1 (ggid,passwd) values ('test2','this will fail');
ERROR 23000: Duplicate entry 'test2' for key 'ggid'
insert into t1 (ggid,id) values ('this will fail',1);
ERROR 23000: Duplicate entry '1' for key 'PRIMARY'
select * from t1 where ggid='test1';
id ggid email passwd
1 test1 xxx
select * from t1 where passwd='xxx';
id ggid email passwd
1 test1 xxx
select * from t1 where id=2;
id ggid email passwd
2 test2 yyy
replace into t1 (ggid,id) values ('this will work',1);
replace into t1 (ggid,passwd) values ('test2','this will work');
update t1 set id=100,ggid='test2' where id=1;
ERROR 23000: Duplicate entry 'test2' for key 'ggid'
select * from t1;
id ggid email passwd
1 this will work
4 test2 this will work
select * from t1 where id=1;
id ggid email passwd
1 this will work
select * from t1 where id=999;
id ggid email passwd
drop table t1;
CREATE TABLE t1 (
user_name varchar(12), user_name varchar(12),
password text, password text,
subscribed char(1), subscribed char(1),
...@@ -1751,13 +1714,13 @@ Variable_name Value ...@@ -1751,13 +1714,13 @@ Variable_name Value
Innodb_page_size 16384 Innodb_page_size 16384
show status like "Innodb_rows_deleted"; show status like "Innodb_rows_deleted";
Variable_name Value Variable_name Value
Innodb_rows_deleted 70 Innodb_rows_deleted 69
show status like "Innodb_rows_inserted"; show status like "Innodb_rows_inserted";
Variable_name Value Variable_name Value
Innodb_rows_inserted 1083 Innodb_rows_inserted 1080
show status like "Innodb_rows_updated"; show status like "Innodb_rows_updated";
Variable_name Value Variable_name Value
Innodb_rows_updated 886 Innodb_rows_updated 885
show status like "Innodb_row_lock_waits"; show status like "Innodb_row_lock_waits";
Variable_name Value Variable_name Value
Innodb_row_lock_waits 0 Innodb_row_lock_waits 0
...@@ -3189,3 +3152,36 @@ c25 CHAR(255), c26 CHAR(255), c27 CHAR(255), c28 CHAR(255), ...@@ -3189,3 +3152,36 @@ c25 CHAR(255), c26 CHAR(255), c27 CHAR(255), c28 CHAR(255),
c29 CHAR(255), c30 CHAR(255), c31 CHAR(255), c32 CHAR(255) c29 CHAR(255), c30 CHAR(255), c31 CHAR(255), c32 CHAR(255)
) ENGINE = InnoDB; ) ENGINE = InnoDB;
ERROR 42000: Row size too large. The maximum row size for the used table type, not counting BLOBs, is 8126. You have to change some columns to TEXT or BLOBs ERROR 42000: Row size too large. The maximum row size for the used table type, not counting BLOBs, is 8126. You have to change some columns to TEXT or BLOBs
SET TX_ISOLATION='read-committed';
SET AUTOCOMMIT=0;
DROP TABLE IF EXISTS t1, t2;
Warnings:
Note 1051 Unknown table 't1'
Note 1051 Unknown table 't2'
CREATE TABLE t1 ( a int ) ENGINE=InnoDB;
CREATE TABLE t2 LIKE t1;
SELECT * FROM t2;
a
SET TX_ISOLATION='read-committed';
SET AUTOCOMMIT=0;
INSERT INTO t1 VALUES (1);
COMMIT;
SELECT * FROM t1 WHERE a=1;
a
1
SET TX_ISOLATION='read-committed';
SET AUTOCOMMIT=0;
SELECT * FROM t2;
a
SET TX_ISOLATION='read-committed';
SET AUTOCOMMIT=0;
INSERT INTO t1 VALUES (2);
COMMIT;
SELECT * FROM t1 WHERE a=2;
a
2
SELECT * FROM t1 WHERE a=2;
a
2
DROP TABLE t1;
DROP TABLE t2;
drop table if exists t1;
CREATE TABLE t1 (
id int(11) NOT NULL auto_increment,
ggid varchar(32) binary DEFAULT '' NOT NULL,
email varchar(64) DEFAULT '' NOT NULL,
passwd varchar(32) binary DEFAULT '' NOT NULL,
PRIMARY KEY (id),
UNIQUE ggid (ggid)
) ENGINE=innodb;
insert into t1 (ggid,passwd) values ('test1','xxx');
insert into t1 (ggid,passwd) values ('test2','yyy');
insert into t1 (ggid,passwd) values ('test2','this will fail');
ERROR 23000: Duplicate entry 'test2' for key 'ggid'
insert into t1 (ggid,id) values ('this will fail',1);
ERROR 23000: Duplicate entry '1' for key 'PRIMARY'
select * from t1 where ggid='test1';
id ggid email passwd
1 test1 xxx
select * from t1 where passwd='xxx';
id ggid email passwd
1 test1 xxx
select * from t1 where id=2;
id ggid email passwd
2 test2 yyy
replace into t1 (ggid,id) values ('this will work',1);
replace into t1 (ggid,passwd) values ('test2','this will work');
update t1 set id=100,ggid='test2' where id=1;
ERROR 23000: Duplicate entry 'test2' for key 'ggid'
select * from t1;
id ggid email passwd
1 this will work
3 test2 this will work
select * from t1 where id=1;
id ggid email passwd
1 this will work
select * from t1 where id=999;
id ggid email passwd
drop table t1;
End of tests
--innodb_locks_unsafe_for_binlog=true --innodb_lock_wait_timeout=2
-- source include/not_embedded.inc
-- source include/have_innodb.inc
# basic tests of semi-consistent reads
connect (a,localhost,root,,);
connect (b,localhost,root,,);
connection a;
set session transaction isolation level read committed;
create table t1(a int not null) engine=innodb DEFAULT CHARSET=latin1;
insert into t1 values (1),(2),(3),(4),(5),(6),(7);
set autocommit=0;
# this should lock the entire table
select * from t1 where a=3 lock in share mode;
connection b;
set session transaction isolation level read committed;
set autocommit=0;
-- error ER_LOCK_WAIT_TIMEOUT
update t1 set a=10 where a=5;
connection a;
commit;
connection b;
update t1 set a=10 where a=5;
connection a;
-- error ER_LOCK_WAIT_TIMEOUT
select * from t1 where a=2 for update;
# this should lock the records (1),(2)
select * from t1 where a=2 limit 1 for update;
connection b;
update t1 set a=11 where a=6;
-- error ER_LOCK_WAIT_TIMEOUT
update t1 set a=12 where a=2;
-- error ER_LOCK_WAIT_TIMEOUT
update t1 set a=13 where a=1;
connection a;
commit;
connection b;
update t1 set a=14 where a=1;
commit;
connection a;
select * from t1;
drop table t1;
connection default;
disconnect a;
disconnect b;
...@@ -326,39 +326,6 @@ select * from t1; ...@@ -326,39 +326,6 @@ select * from t1;
select * from t2; select * from t2;
drop table t1,t2; drop table t1,t2;
#
# Search on unique key
#
CREATE TABLE t1 (
id int(11) NOT NULL auto_increment,
ggid varchar(32) binary DEFAULT '' NOT NULL,
email varchar(64) DEFAULT '' NOT NULL,
passwd varchar(32) binary DEFAULT '' NOT NULL,
PRIMARY KEY (id),
UNIQUE ggid (ggid)
) ENGINE=innodb;
insert into t1 (ggid,passwd) values ('test1','xxx');
insert into t1 (ggid,passwd) values ('test2','yyy');
-- error ER_DUP_ENTRY
insert into t1 (ggid,passwd) values ('test2','this will fail');
-- error ER_DUP_ENTRY
insert into t1 (ggid,id) values ('this will fail',1);
select * from t1 where ggid='test1';
select * from t1 where passwd='xxx';
select * from t1 where id=2;
replace into t1 (ggid,id) values ('this will work',1);
replace into t1 (ggid,passwd) values ('test2','this will work');
-- error ER_DUP_ENTRY
update t1 set id=100,ggid='test2' where id=1;
select * from t1;
select * from t1 where id=1;
select * from t1 where id=999;
drop table t1;
# #
# ORDER BY on not primary key # ORDER BY on not primary key
# #
...@@ -2323,6 +2290,48 @@ CREATE TABLE t1 ( ...@@ -2323,6 +2290,48 @@ CREATE TABLE t1 (
c29 CHAR(255), c30 CHAR(255), c31 CHAR(255), c32 CHAR(255) c29 CHAR(255), c30 CHAR(255), c31 CHAR(255), c32 CHAR(255)
) ENGINE = InnoDB; ) ENGINE = InnoDB;
#
# Bug #21409 Incorrect result returned when in READ-COMMITTED with
# query_cache ON
#
CONNECT (c1,localhost,root,,);
CONNECT (c2,localhost,root,,);
CONNECTION c1;
SET TX_ISOLATION='read-committed';
SET AUTOCOMMIT=0;
DROP TABLE IF EXISTS t1, t2;
CREATE TABLE t1 ( a int ) ENGINE=InnoDB;
CREATE TABLE t2 LIKE t1;
SELECT * FROM t2;
CONNECTION c2;
SET TX_ISOLATION='read-committed';
SET AUTOCOMMIT=0;
INSERT INTO t1 VALUES (1);
COMMIT;
CONNECTION c1;
SELECT * FROM t1 WHERE a=1;
DISCONNECT c1;
DISCONNECT c2;
CONNECT (c1,localhost,root,,);
CONNECT (c2,localhost,root,,);
CONNECTION c1;
SET TX_ISOLATION='read-committed';
SET AUTOCOMMIT=0;
SELECT * FROM t2;
CONNECTION c2;
SET TX_ISOLATION='read-committed';
SET AUTOCOMMIT=0;
INSERT INTO t1 VALUES (2);
COMMIT;
CONNECTION c1;
# The result set below should be the same for both selects
SELECT * FROM t1 WHERE a=2;
SELECT * FROM t1 WHERE a=2;
DROP TABLE t1;
DROP TABLE t2;
DISCONNECT c1;
DISCONNECT c2;
####################################################################### #######################################################################
# # # #
# Please, DO NOT TOUCH this file as well as the innodb.result file. # # Please, DO NOT TOUCH this file as well as the innodb.result file. #
......
# This test runs with old-style locking, as:
# --innodb-autoinc-lock-mode=0
-- source include/have_innodb.inc
--disable_warnings
drop table if exists t1;
--enable_warnings
#
# Search on unique key
#
CREATE TABLE t1 (
id int(11) NOT NULL auto_increment,
ggid varchar(32) binary DEFAULT '' NOT NULL,
email varchar(64) DEFAULT '' NOT NULL,
passwd varchar(32) binary DEFAULT '' NOT NULL,
PRIMARY KEY (id),
UNIQUE ggid (ggid)
) ENGINE=innodb;
insert into t1 (ggid,passwd) values ('test1','xxx');
insert into t1 (ggid,passwd) values ('test2','yyy');
-- error ER_DUP_ENTRY
insert into t1 (ggid,passwd) values ('test2','this will fail');
-- error ER_DUP_ENTRY
insert into t1 (ggid,id) values ('this will fail',1);
select * from t1 where ggid='test1';
select * from t1 where passwd='xxx';
select * from t1 where id=2;
replace into t1 (ggid,id) values ('this will work',1);
replace into t1 (ggid,passwd) values ('test2','this will work');
-- error ER_DUP_ENTRY
update t1 set id=100,ggid='test2' where id=1;
select * from t1;
select * from t1 where id=1;
select * from t1 where id=999;
drop table t1;
--echo End of tests
...@@ -881,7 +881,7 @@ buf_LRU_block_free_non_file_page( ...@@ -881,7 +881,7 @@ buf_LRU_block_free_non_file_page(
UT_LIST_ADD_FIRST(free, buf_pool->free, block); UT_LIST_ADD_FIRST(free, buf_pool->free, block);
block->in_free_list = TRUE; block->in_free_list = TRUE;
UNIV_MEM_FREE(block->frame, UNIV_PAGE_SIZE); UNIV_MEM_ASSERT_AND_FREE(block->frame, UNIV_PAGE_SIZE);
if (srv_use_awe && block->frame) { if (srv_use_awe && block->frame) {
/* Add to the list of mapped pages */ /* Add to the list of mapped pages */
......
...@@ -441,6 +441,8 @@ dict_table_autoinc_initialize( ...@@ -441,6 +441,8 @@ dict_table_autoinc_initialize(
dict_table_t* table, /* in: table */ dict_table_t* table, /* in: table */
ib_longlong value) /* in: next value to assign to a row */ ib_longlong value) /* in: next value to assign to a row */
{ {
ut_ad(mutex_own(&table->autoinc_mutex));
table->autoinc_inited = TRUE; table->autoinc_inited = TRUE;
table->autoinc = value; table->autoinc = value;
} }
...@@ -457,6 +459,8 @@ dict_table_autoinc_read( ...@@ -457,6 +459,8 @@ dict_table_autoinc_read(
{ {
ib_longlong value; ib_longlong value;
ut_ad(mutex_own(&table->autoinc_mutex));
if (!table->autoinc_inited) { if (!table->autoinc_inited) {
value = 0; value = 0;
......
...@@ -551,11 +551,13 @@ dict_load_fields( ...@@ -551,11 +551,13 @@ dict_load_fields(
Loads definitions for table indexes. Adds them to the data dictionary Loads definitions for table indexes. Adds them to the data dictionary
cache. */ cache. */
static static
ibool ulint
dict_load_indexes( dict_load_indexes(
/*==============*/ /*==============*/
/* out: TRUE if ok, FALSE if corruption /* out: DB_SUCCESS if ok, DB_CORRUPTION
of dictionary table */ if corruption of dictionary table or
DB_UNSUPPORTED if table has unknown index
type */
dict_table_t* table, /* in: table */ dict_table_t* table, /* in: table */
mem_heap_t* heap) /* in: memory heap for temporary storage */ mem_heap_t* heap) /* in: memory heap for temporary storage */
{ {
...@@ -578,6 +580,7 @@ dict_load_indexes( ...@@ -578,6 +580,7 @@ dict_load_indexes(
ibool is_sys_table; ibool is_sys_table;
dulint id; dulint id;
mtr_t mtr; mtr_t mtr;
ulint error = DB_SUCCESS;
ut_ad(mutex_own(&(dict_sys->mutex))); ut_ad(mutex_own(&(dict_sys->mutex)));
...@@ -624,10 +627,8 @@ dict_load_indexes( ...@@ -624,10 +627,8 @@ dict_load_indexes(
dict_load_report_deleted_index(table->name, dict_load_report_deleted_index(table->name,
ULINT_UNDEFINED); ULINT_UNDEFINED);
btr_pcur_close(&pcur); error = DB_CORRUPTION;
mtr_commit(&mtr); goto func_exit;
return(FALSE);
} }
field = rec_get_nth_field_old(rec, 1, &len); field = rec_get_nth_field_old(rec, 1, &len);
...@@ -653,7 +654,18 @@ dict_load_indexes( ...@@ -653,7 +654,18 @@ dict_load_indexes(
field = rec_get_nth_field_old(rec, 8, &len); field = rec_get_nth_field_old(rec, 8, &len);
page_no = mach_read_from_4(field); page_no = mach_read_from_4(field);
if (page_no == FIL_NULL) { /* We check for unsupported types first, so that the
subsequent checks are relevant for the supported types. */
if (type & ~(DICT_CLUSTERED | DICT_UNIQUE)) {
fprintf(stderr,
"InnoDB: Error: unknown type %lu"
" of index %s of table %s\n",
(ulong) type, name_buf, table->name);
error = DB_UNSUPPORTED;
goto func_exit;
} else if (page_no == FIL_NULL) {
fprintf(stderr, fprintf(stderr,
"InnoDB: Error: trying to load index %s" "InnoDB: Error: trying to load index %s"
...@@ -661,14 +673,10 @@ dict_load_indexes( ...@@ -661,14 +673,10 @@ dict_load_indexes(
"InnoDB: but the index tree has been freed!\n", "InnoDB: but the index tree has been freed!\n",
name_buf, table->name); name_buf, table->name);
btr_pcur_close(&pcur); error = DB_CORRUPTION;
mtr_commit(&mtr); goto func_exit;
} else if ((type & DICT_CLUSTERED) == 0
return(FALSE); && NULL == dict_table_get_first_index(table)) {
}
if ((type & DICT_CLUSTERED) == 0
&& NULL == dict_table_get_first_index(table)) {
fprintf(stderr, fprintf(stderr,
"InnoDB: Error: trying to load index %s" "InnoDB: Error: trying to load index %s"
...@@ -677,18 +685,14 @@ dict_load_indexes( ...@@ -677,18 +685,14 @@ dict_load_indexes(
" is not clustered!\n", " is not clustered!\n",
name_buf, table->name); name_buf, table->name);
btr_pcur_close(&pcur); error = DB_CORRUPTION;
mtr_commit(&mtr); goto func_exit;
} else if (is_sys_table
return(FALSE); && ((type & DICT_CLUSTERED)
} || ((table == dict_sys->sys_tables)
&& (name_len == (sizeof "ID_IND") - 1)
if (is_sys_table && (0 == ut_memcmp(name_buf,
&& ((type & DICT_CLUSTERED) "ID_IND", name_len))))) {
|| ((table == dict_sys->sys_tables)
&& (name_len == (sizeof "ID_IND") - 1)
&& (0 == ut_memcmp(name_buf, "ID_IND",
name_len))))) {
/* The index was created in memory already at booting /* The index was created in memory already at booting
of the database server */ of the database server */
...@@ -704,10 +708,11 @@ dict_load_indexes( ...@@ -704,10 +708,11 @@ dict_load_indexes(
btr_pcur_move_to_next_user_rec(&pcur, &mtr); btr_pcur_move_to_next_user_rec(&pcur, &mtr);
} }
func_exit:
btr_pcur_close(&pcur); btr_pcur_close(&pcur);
mtr_commit(&mtr); mtr_commit(&mtr);
return(TRUE); return(error);
} }
/************************************************************************ /************************************************************************
...@@ -857,11 +862,20 @@ dict_load_table( ...@@ -857,11 +862,20 @@ dict_load_table(
mem_heap_empty(heap); mem_heap_empty(heap);
dict_load_indexes(table, heap); err = dict_load_indexes(table, heap);
err = dict_load_foreigns(table->name, TRUE); /* If the force recovery flag is set, we open the table irrespective
of the error condition, since the user may want to dump data from the
clustered index. However we load the foreign key information only if
all indexes were loaded. */
if (err != DB_SUCCESS && !srv_force_recovery) {
dict_mem_table_free(table);
table = NULL;
} else if (err == DB_SUCCESS) {
err = dict_load_foreigns(table->name, TRUE);
}
#if 0 #if 0
if (err != DB_SUCCESS) { if (err != DB_SUCCESS && table != NULL) {
mutex_enter(&dict_foreign_err_mutex); mutex_enter(&dict_foreign_err_mutex);
......
...@@ -129,6 +129,7 @@ static my_bool innobase_locks_unsafe_for_binlog = FALSE; ...@@ -129,6 +129,7 @@ static my_bool innobase_locks_unsafe_for_binlog = FALSE;
static my_bool innobase_rollback_on_timeout = FALSE; static my_bool innobase_rollback_on_timeout = FALSE;
static my_bool innobase_create_status_file = FALSE; static my_bool innobase_create_status_file = FALSE;
static my_bool innobase_stats_on_metadata = TRUE; static my_bool innobase_stats_on_metadata = TRUE;
static my_bool innobase_use_adaptive_hash_indexes = TRUE;
static char* internal_innobase_data_file_path = NULL; static char* internal_innobase_data_file_path = NULL;
...@@ -1246,8 +1247,7 @@ innobase_invalidate_query_cache( ...@@ -1246,8 +1247,7 @@ innobase_invalidate_query_cache(
} }
/********************************************************************* /*********************************************************************
Display an SQL identifier. Display an SQL identifier. */
This definition must match the one in innobase/ut/ut0ut.c! */
extern "C" extern "C"
void void
innobase_print_identifier( innobase_print_identifier(
...@@ -1635,6 +1635,9 @@ innobase_init( ...@@ -1635,6 +1635,9 @@ innobase_init(
srv_stats_on_metadata = (ibool) innobase_stats_on_metadata; srv_stats_on_metadata = (ibool) innobase_stats_on_metadata;
srv_use_adaptive_hash_indexes =
(ibool) innobase_use_adaptive_hash_indexes;
srv_print_verbose_log = mysqld_embedded ? 0 : 1; srv_print_verbose_log = mysqld_embedded ? 0 : 1;
/* Store the default charset-collation number of this MySQL /* Store the default charset-collation number of this MySQL
...@@ -2320,13 +2323,18 @@ ha_innobase::open( ...@@ -2320,13 +2323,18 @@ ha_innobase::open(
if (NULL == ib_table) { if (NULL == ib_table) {
ut_print_timestamp(stderr); ut_print_timestamp(stderr);
sql_print_error("Cannot find table %s from the internal data " sql_print_error("Cannot find or open table %s from\n"
"dictionary\nof InnoDB though the .frm file " "the internal data dictionary of InnoDB "
"for the table exists. Maybe you\nhave " "though the .frm file for the\n"
"deleted and recreated InnoDB data files but " "table exists. Maybe you have deleted and "
"have forgotten\nto delete the corresponding " "recreated InnoDB data\n"
".frm files of InnoDB tables, or you\n" "files but have forgotten to delete the "
"have moved .frm files to another database?\n" "corresponding .frm files\n"
"of InnoDB tables, or you have moved .frm "
"files to another database?\n"
"or, the table contains indexes that this "
"version of the engine\n"
"doesn't support.\n"
"See http://dev.mysql.com/doc/refman/5.1/en/innodb-troubleshooting.html\n" "See http://dev.mysql.com/doc/refman/5.1/en/innodb-troubleshooting.html\n"
"how you can resolve the problem.\n", "how you can resolve the problem.\n",
norm_name); norm_name);
...@@ -3476,6 +3484,7 @@ ha_innobase::write_row( ...@@ -3476,6 +3484,7 @@ ha_innobase::write_row(
/* Handle duplicate key errors */ /* Handle duplicate key errors */
if (auto_inc_used) { if (auto_inc_used) {
ulint err;
ulonglong auto_inc; ulonglong auto_inc;
/* Note the number of rows processed for this statement, used /* Note the number of rows processed for this statement, used
...@@ -3529,7 +3538,11 @@ ha_innobase::write_row( ...@@ -3529,7 +3538,11 @@ ha_innobase::write_row(
ut_a(prebuilt->table->autoinc_increment > 0); ut_a(prebuilt->table->autoinc_increment > 0);
auto_inc += prebuilt->table->autoinc_increment; auto_inc += prebuilt->table->autoinc_increment;
innobase_set_max_autoinc(auto_inc); err = innobase_set_max_autoinc(auto_inc);
if (err != DB_SUCCESS) {
error = err;
}
} }
break; break;
} }
...@@ -3765,7 +3778,7 @@ ha_innobase::update_row( ...@@ -3765,7 +3778,7 @@ ha_innobase::update_row(
if (auto_inc != 0) { if (auto_inc != 0) {
auto_inc += prebuilt->table->autoinc_increment; auto_inc += prebuilt->table->autoinc_increment;
innobase_set_max_autoinc(auto_inc); error = innobase_set_max_autoinc(auto_inc);
} }
} }
...@@ -6304,6 +6317,9 @@ ha_innobase::start_stmt( ...@@ -6304,6 +6317,9 @@ ha_innobase::start_stmt(
innobase_release_stat_resources(trx); innobase_release_stat_resources(trx);
/* Reset the AUTOINC statement level counter for multi-row INSERTs. */
trx->n_autoinc_rows = 0;
prebuilt->sql_stat_start = TRUE; prebuilt->sql_stat_start = TRUE;
prebuilt->hint_need_to_fetch_extra_cols = 0; prebuilt->hint_need_to_fetch_extra_cols = 0;
reset_template(prebuilt); reset_template(prebuilt);
...@@ -6446,9 +6462,6 @@ ha_innobase::external_lock( ...@@ -6446,9 +6462,6 @@ ha_innobase::external_lock(
innobase_register_stmt(ht, thd); innobase_register_stmt(ht, thd);
} }
trx->n_mysql_tables_in_use++;
prebuilt->mysql_has_locked = TRUE;
if (trx->isolation_level == TRX_ISO_SERIALIZABLE if (trx->isolation_level == TRX_ISO_SERIALIZABLE
&& prebuilt->select_lock_type == LOCK_NONE && prebuilt->select_lock_type == LOCK_NONE
&& thd_test_options(thd, && thd_test_options(thd,
...@@ -6497,6 +6510,9 @@ ha_innobase::external_lock( ...@@ -6497,6 +6510,9 @@ ha_innobase::external_lock(
trx->mysql_n_tables_locked++; trx->mysql_n_tables_locked++;
} }
trx->n_mysql_tables_in_use++;
prebuilt->mysql_has_locked = TRUE;
DBUG_RETURN(0); DBUG_RETURN(0);
} }
...@@ -7120,8 +7136,8 @@ the value of the auto-inc counter. */ ...@@ -7120,8 +7136,8 @@ the value of the auto-inc counter. */
int int
ha_innobase::innobase_read_and_init_auto_inc( ha_innobase::innobase_read_and_init_auto_inc(
/*=========================================*/ /*=========================================*/
/* out: 0 or error code: /* out: 0 or generic MySQL
deadlock or lock wait timeout */ error code */
longlong* value) /* out: the autoinc value */ longlong* value) /* out: the autoinc value */
{ {
longlong auto_inc; longlong auto_inc;
...@@ -7178,9 +7194,9 @@ ha_innobase::innobase_read_and_init_auto_inc( ...@@ -7178,9 +7194,9 @@ ha_innobase::innobase_read_and_init_auto_inc(
++auto_inc; ++auto_inc;
dict_table_autoinc_initialize(innodb_table, auto_inc); dict_table_autoinc_initialize(innodb_table, auto_inc);
} else { } else {
fprintf(stderr, " InnoDB error: Couldn't read the " fprintf(stderr, " InnoDB error (%lu): Couldn't read "
"max AUTOINC value from index (%s).\n", "the max AUTOINC value from the index (%s).\n",
index->name); error, index->name);
mysql_error = 1; mysql_error = 1;
} }
...@@ -7217,6 +7233,11 @@ ha_innobase::innobase_get_auto_increment( ...@@ -7217,6 +7233,11 @@ ha_innobase::innobase_get_auto_increment(
{ {
ulong error; ulong error;
*value = 0;
/* Note: If the table is not initialized when we attempt the
read below. We initialize the table's auto-inc counter and
always do a reread of the AUTOINC value. */
do { do {
error = innobase_autoinc_lock(); error = innobase_autoinc_lock();
...@@ -7256,7 +7277,16 @@ ha_innobase::innobase_get_auto_increment( ...@@ -7256,7 +7277,16 @@ ha_innobase::innobase_get_auto_increment(
} else { } else {
*value = (ulonglong) autoinc; *value = (ulonglong) autoinc;
} }
/* A deadlock error during normal processing is OK
and can be ignored. */
} else if (error != DB_DEADLOCK) {
ut_print_timestamp(stderr);
sql_print_error(" InnoDB Error %lu in "
"::innobase_get_auto_increment()",
error);
} }
} while (*value == 0 && error == DB_SUCCESS); } while (*value == 0 && error == DB_SUCCESS);
return(error); return(error);
...@@ -7272,7 +7302,7 @@ we have a table-level lock). offset, increment, nb_desired_values are ignored. ...@@ -7272,7 +7302,7 @@ we have a table-level lock). offset, increment, nb_desired_values are ignored.
void void
ha_innobase::get_auto_increment( ha_innobase::get_auto_increment(
/*=================================*/ /*============================*/
ulonglong offset, /* in: */ ulonglong offset, /* in: */
ulonglong increment, /* in: table autoinc increment */ ulonglong increment, /* in: table autoinc increment */
ulonglong nb_desired_values, /* in: number of values reqd */ ulonglong nb_desired_values, /* in: number of values reqd */
...@@ -7289,13 +7319,6 @@ ha_innobase::get_auto_increment( ...@@ -7289,13 +7319,6 @@ ha_innobase::get_auto_increment(
error = innobase_get_auto_increment(&autoinc); error = innobase_get_auto_increment(&autoinc);
if (error != DB_SUCCESS) { if (error != DB_SUCCESS) {
/* This should never happen in the code > ver 5.0.6,
since we call this function only after the counter
has been initialized. */
ut_print_timestamp(stderr);
sql_print_error("Error %lu in ::get_auto_increment()", error);
*first_value = (~(ulonglong) 0); *first_value = (~(ulonglong) 0);
return; return;
} }
...@@ -7310,6 +7333,11 @@ ha_innobase::get_auto_increment( ...@@ -7310,6 +7333,11 @@ ha_innobase::get_auto_increment(
trx = prebuilt->trx; trx = prebuilt->trx;
/* Note: We can't rely on *first_value since some MySQL engines,
in particular the partition engine, don't initialize it to 0 when
invoking this method. So we are not sure if it's guaranteed to
be 0 or not. */
/* Called for the first time ? */ /* Called for the first time ? */
if (trx->n_autoinc_rows == 0) { if (trx->n_autoinc_rows == 0) {
...@@ -7318,16 +7346,16 @@ ha_innobase::get_auto_increment( ...@@ -7318,16 +7346,16 @@ ha_innobase::get_auto_increment(
/* It's possible for nb_desired_values to be 0: /* It's possible for nb_desired_values to be 0:
e.g., INSERT INTO T1(C) SELECT C FROM T2; */ e.g., INSERT INTO T1(C) SELECT C FROM T2; */
if (nb_desired_values == 0) { if (nb_desired_values == 0) {
trx->n_autoinc_rows = 1; trx->n_autoinc_rows = 1;
} }
set_if_bigger(*first_value, autoinc); set_if_bigger(*first_value, autoinc);
/* Not in the middle of a mult-row INSERT. */ /* Not in the middle of a mult-row INSERT. */
} else if (prebuilt->last_value == 0) { } else if (prebuilt->last_value == 0) {
set_if_bigger(*first_value, autoinc); set_if_bigger(*first_value, autoinc);
} }
*nb_reserved_values = trx->n_autoinc_rows; *nb_reserved_values = trx->n_autoinc_rows;
/* With old style AUTOINC locking we only update the table's /* With old style AUTOINC locking we only update the table's
...@@ -7359,7 +7387,9 @@ ha_innobase::get_auto_increment( ...@@ -7359,7 +7387,9 @@ ha_innobase::get_auto_increment(
/* See comment in handler.h */ /* See comment in handler.h */
int int
ha_innobase::reset_auto_increment(ulonglong value) ha_innobase::reset_auto_increment(
/*==============================*/
ulonglong value) /* in: new value for table autoinc */
{ {
DBUG_ENTER("ha_innobase::reset_auto_increment"); DBUG_ENTER("ha_innobase::reset_auto_increment");
...@@ -7923,6 +7953,11 @@ static MYSQL_SYSVAR_BOOL(stats_on_metadata, innobase_stats_on_metadata, ...@@ -7923,6 +7953,11 @@ static MYSQL_SYSVAR_BOOL(stats_on_metadata, innobase_stats_on_metadata,
"Enable statistics gathering for metadata commands such as SHOW TABLE STATUS (on by default)", "Enable statistics gathering for metadata commands such as SHOW TABLE STATUS (on by default)",
NULL, NULL, TRUE); NULL, NULL, TRUE);
static MYSQL_SYSVAR_BOOL(use_adaptive_hash_indexes, innobase_use_adaptive_hash_indexes,
PLUGIN_VAR_OPCMDARG | PLUGIN_VAR_READONLY,
"Enable the InnoDB adaptive hash indexes (enabled by default)",
NULL, NULL, TRUE);
static MYSQL_SYSVAR_LONG(additional_mem_pool_size, innobase_additional_mem_pool_size, static MYSQL_SYSVAR_LONG(additional_mem_pool_size, innobase_additional_mem_pool_size,
PLUGIN_VAR_RQCMDARG | PLUGIN_VAR_READONLY, PLUGIN_VAR_RQCMDARG | PLUGIN_VAR_READONLY,
"Size of a memory pool InnoDB uses to store data dictionary information and other internal data structures.", "Size of a memory pool InnoDB uses to store data dictionary information and other internal data structures.",
...@@ -8051,6 +8086,7 @@ static struct st_mysql_sys_var* innobase_system_variables[]= { ...@@ -8051,6 +8086,7 @@ static struct st_mysql_sys_var* innobase_system_variables[]= {
MYSQL_SYSVAR(open_files), MYSQL_SYSVAR(open_files),
MYSQL_SYSVAR(rollback_on_timeout), MYSQL_SYSVAR(rollback_on_timeout),
MYSQL_SYSVAR(stats_on_metadata), MYSQL_SYSVAR(stats_on_metadata),
MYSQL_SYSVAR(use_adaptive_hash_indexes),
MYSQL_SYSVAR(status_file), MYSQL_SYSVAR(status_file),
MYSQL_SYSVAR(support_xa), MYSQL_SYSVAR(support_xa),
MYSQL_SYSVAR(sync_spin_loops), MYSQL_SYSVAR(sync_spin_loops),
......
...@@ -250,17 +250,3 @@ int thd_binlog_format(const MYSQL_THD thd); ...@@ -250,17 +250,3 @@ int thd_binlog_format(const MYSQL_THD thd);
*/ */
void thd_mark_transaction_to_rollback(MYSQL_THD thd, bool all); void thd_mark_transaction_to_rollback(MYSQL_THD thd, bool all);
} }
/*
don't delete it - it may be re-enabled later
as an optimization for the most common case InnoDB+binlog
*/
#if 0
int innobase_report_binlog_offset_and_commit(
THD* thd,
void* trx_handle,
char* log_file_name,
my_off_t end_offset);
int innobase_commit_complete(void* trx_handle);
void innobase_store_binlog_offset_and_flush_log(char *binlog_name,longlong offset);
#endif
...@@ -2900,7 +2900,7 @@ ibuf_insert_to_index_page( ...@@ -2900,7 +2900,7 @@ ibuf_insert_to_index_page(
ut_print_timestamp(stderr); ut_print_timestamp(stderr);
fprintf(stderr, fprintf(stderr,
"InnoDB: Error: Insert buffer insert" " InnoDB: Error: Insert buffer insert"
" fails; page free %lu," " fails; page free %lu,"
" dtuple size %lu\n", " dtuple size %lu\n",
(ulong) page_get_max_insert_size( (ulong) page_get_max_insert_size(
...@@ -2925,7 +2925,7 @@ ibuf_insert_to_index_page( ...@@ -2925,7 +2925,7 @@ ibuf_insert_to_index_page(
buf_frame_get_page_no(page), buf_frame_get_page_no(page),
IBUF_BITMAP_FREE, mtr); IBUF_BITMAP_FREE, mtr);
fprintf(stderr, "Bitmap bits %lu\n", fprintf(stderr, "InnoDB: Bitmap bits %lu\n",
(ulong) old_bits); (ulong) old_bits);
fputs("InnoDB: Submit a detailed bug report" fputs("InnoDB: Submit a detailed bug report"
......
...@@ -61,12 +61,14 @@ Created 5/24/1996 Heikki Tuuri ...@@ -61,12 +61,14 @@ Created 5/24/1996 Heikki Tuuri
activated by the operation would activated by the operation would
lead to a duplicate key in some lead to a duplicate key in some
table */ table */
#define DB_TOO_MANY_CONCURRENT_TRXS 47 /* when InnoDB runs out of the #define DB_TOO_MANY_CONCURRENT_TRXS 47 /* when InnoDB runs out of the
preconfigured undo slots, this can preconfigured undo slots, this can
only happen when there are too many only happen when there are too many
concurrent transactions */ concurrent transactions */
#define DB_UNSUPPORTED 48 /* when InnoDB sees any artefact or
a feature that it can't recoginize or
work with e.g., FT indexes created by
a later version of the engine. */
/* The following are partial failure codes */ /* The following are partial failure codes */
#define DB_FAIL 1000 #define DB_FAIL 1000
#define DB_OVERFLOW 1001 #define DB_OVERFLOW 1001
......
#ifndef HA_INNODB_PROTOTYPES_H #ifndef HA_INNODB_PROTOTYPES_H
#define HA_INNODB_PROTOTYPES_H #define HA_INNODB_PROTOTYPES_H
#ifndef UNIV_HOTBACKUP
#include "univ.i" /* ulint, uint */ #include "univ.i" /* ulint, uint */
#include "m_ctype.h" /* CHARSET_INFO */ #include "m_ctype.h" /* CHARSET_INFO */
...@@ -22,6 +24,19 @@ innobase_convert_string( ...@@ -22,6 +24,19 @@ innobase_convert_string(
CHARSET_INFO* from_cs, CHARSET_INFO* from_cs,
uint* errors); uint* errors);
/*********************************************************************
Display an SQL identifier. */
void
innobase_print_identifier(
/*======================*/
FILE* f, /* in: output stream */
trx_t* trx, /* in: transaction */
ibool table_id,/* in: TRUE=print a table name,
FALSE=print other identifier */
const char* name, /* in: name to print */
ulint namelen);/* in: length of name */
/********************************************************************** /**********************************************************************
Returns true if the thread is the replication thread on the slave Returns true if the thread is the replication thread on the slave
server. Used in srv_conc_enter_innodb() to determine if the thread server. Used in srv_conc_enter_innodb() to determine if the thread
...@@ -49,3 +64,4 @@ thd_has_edited_nontrans_tables( ...@@ -49,3 +64,4 @@ thd_has_edited_nontrans_tables(
void* thd); /* in: thread handle (THD*) */ void* thd); /* in: thread handle (THD*) */
#endif #endif
#endif
...@@ -327,6 +327,17 @@ mach_write_to_2_little_endian( ...@@ -327,6 +327,17 @@ mach_write_to_2_little_endian(
byte* dest, /* in: where to write */ byte* dest, /* in: where to write */
ulint n); /* in: unsigned long int to write */ ulint n); /* in: unsigned long int to write */
/*************************************************************
Convert integral type from storage byte order (big endian) to
host byte order. */
UNIV_INLINE
void
mach_read_int_type(
/*===============*/
byte* dest, /* out: where to write */
const byte* src, /* in: where to read from */
ulint len, /* in: length of src */
ibool unsigned_type); /* in: signed or unsigned flag */
#ifndef UNIV_NONINL #ifndef UNIV_NONINL
#include "mach0data.ic" #include "mach0data.ic"
#endif #endif
......
...@@ -7,6 +7,8 @@ to the machine format. ...@@ -7,6 +7,8 @@ to the machine format.
Created 11/28/1995 Heikki Tuuri Created 11/28/1995 Heikki Tuuri
***********************************************************************/ ***********************************************************************/
#include "ut0mem.h"
/*********************************************************** /***********************************************************
The following function is used to store data in one byte. */ The following function is used to store data in one byte. */
UNIV_INLINE UNIV_INLINE
...@@ -689,3 +691,38 @@ mach_write_to_2_little_endian( ...@@ -689,3 +691,38 @@ mach_write_to_2_little_endian(
*dest = (byte)(n & 0xFFUL); *dest = (byte)(n & 0xFFUL);
} }
/*************************************************************
Convert integral type from storage byte order (big endian) to
host byte order. */
UNIV_INLINE
void
mach_read_int_type(
/*===============*/
byte* dest, /* out: where to write */
const byte* src, /* in: where to read from */
ulint len, /* in: length of src */
ibool unsigned_type) /* in: signed or unsigned flag */
{
#ifdef WORDS_BIGENDIAN
memcpy(dest, src, len);
if (!unsigned_type) {
dest[0] ^= 128;
}
#else
byte* ptr;
/* Convert integer data from Innobase to a little-endian format,
sign bit restored to normal. */
for (ptr = dest + len; ptr != dest; ++src) {
--ptr;
*ptr = *src;
}
if (!unsigned_type) {
dest[len - 1] ^= 128;
}
#endif
}
...@@ -60,6 +60,14 @@ mem_heap_validate_or_print( ...@@ -60,6 +60,14 @@ mem_heap_validate_or_print(
ulint* n_blocks); /* out: number of blocks in the heap, ulint* n_blocks); /* out: number of blocks in the heap,
if a NULL pointer is passed as this if a NULL pointer is passed as this
argument, it is ignored */ argument, it is ignored */
/******************************************************************
Validates the contents of a memory heap. */
ibool
mem_heap_validate(
/*==============*/
/* out: TRUE if ok */
mem_heap_t* heap); /* in: memory heap */
#endif /* UNIV_MEM_DEBUG || UNIV_DEBUG */ #endif /* UNIV_MEM_DEBUG || UNIV_DEBUG */
#ifdef UNIV_DEBUG #ifdef UNIV_DEBUG
/****************************************************************** /******************************************************************
...@@ -71,14 +79,6 @@ mem_heap_check( ...@@ -71,14 +79,6 @@ mem_heap_check(
/* out: TRUE if ok */ /* out: TRUE if ok */
mem_heap_t* heap); /* in: memory heap */ mem_heap_t* heap); /* in: memory heap */
#endif /* UNIV_DEBUG */ #endif /* UNIV_DEBUG */
/******************************************************************
Validates the contents of a memory heap. */
ibool
mem_heap_validate(
/*==============*/
/* out: TRUE if ok */
mem_heap_t* heap); /* in: memory heap */
#ifdef UNIV_MEM_DEBUG #ifdef UNIV_MEM_DEBUG
/********************************************************************* /*********************************************************************
TRUE if no memory is currently allocated. */ TRUE if no memory is currently allocated. */
......
...@@ -271,19 +271,16 @@ mem_heap_free_heap_top( ...@@ -271,19 +271,16 @@ mem_heap_free_heap_top(
ut_ad(mem_block_get_start(block) <= mem_block_get_free(block)); ut_ad(mem_block_get_start(block) <= mem_block_get_free(block));
/* In the debug version erase block from top up */ /* In the debug version erase block from top up */
{ mem_erase_buf(old_top, (byte*)block + block->len - old_top);
ulint len = (byte*)block + block->len - old_top;
mem_erase_buf(old_top, len);
UNIV_MEM_FREE(old_top, len);
}
/* Update allocated memory count */ /* Update allocated memory count */
mutex_enter(&mem_hash_mutex); mutex_enter(&mem_hash_mutex);
mem_current_allocated_memory -= (total_size - size); mem_current_allocated_memory -= (total_size - size);
mutex_exit(&mem_hash_mutex); mutex_exit(&mem_hash_mutex);
#else /* UNIV_MEM_DEBUG */ #else /* UNIV_MEM_DEBUG */
UNIV_MEM_FREE(old_top, (byte*)block + block->len - old_top); UNIV_MEM_ASSERT_W(old_top, (byte*)block + block->len - old_top);
#endif /* UNIV_MEM_DEBUG */ #endif /* UNIV_MEM_DEBUG */
UNIV_MEM_ALLOC(old_top, (byte*)block + block->len - old_top);
/* If free == start, we may free the block if it is not the first /* If free == start, we may free the block if it is not the first
one */ one */
...@@ -363,6 +360,7 @@ mem_heap_free_top( ...@@ -363,6 +360,7 @@ mem_heap_free_top(
/* Subtract the free field of block */ /* Subtract the free field of block */
mem_block_set_free(block, mem_block_get_free(block) mem_block_set_free(block, mem_block_get_free(block)
- MEM_SPACE_NEEDED(n)); - MEM_SPACE_NEEDED(n));
UNIV_MEM_ASSERT_W((byte*) block + mem_block_get_free(block), n);
#ifdef UNIV_MEM_DEBUG #ifdef UNIV_MEM_DEBUG
ut_ad(mem_block_get_start(block) <= mem_block_get_free(block)); ut_ad(mem_block_get_start(block) <= mem_block_get_free(block));
...@@ -378,7 +376,11 @@ mem_heap_free_top( ...@@ -378,7 +376,11 @@ mem_heap_free_top(
== mem_block_get_start(block))) { == mem_block_get_start(block))) {
mem_heap_block_free(heap, block); mem_heap_block_free(heap, block);
} else { } else {
UNIV_MEM_FREE((byte*) block + mem_block_get_free(block), n); /* Avoid a bogus UNIV_MEM_ASSERT_W() warning in a
subsequent invocation of mem_heap_free_top().
Originally, this was UNIV_MEM_FREE(), to catch writes
to freed memory. */
UNIV_MEM_ALLOC((byte*) block + mem_block_get_free(block), n);
} }
} }
......
...@@ -801,6 +801,7 @@ rec_offs_set_n_alloc( ...@@ -801,6 +801,7 @@ rec_offs_set_n_alloc(
{ {
ut_ad(offsets); ut_ad(offsets);
ut_ad(n_alloc > 0); ut_ad(n_alloc > 0);
UNIV_MEM_ASSERT_AND_ALLOC(offsets, n_alloc * sizeof *offsets);
offsets[0] = n_alloc; offsets[0] = n_alloc;
} }
......
...@@ -319,9 +319,11 @@ row_mysql_unfreeze_data_dictionary( ...@@ -319,9 +319,11 @@ row_mysql_unfreeze_data_dictionary(
/*===============================*/ /*===============================*/
trx_t* trx); /* in: transaction */ trx_t* trx); /* in: transaction */
/************************************************************************* /*************************************************************************
Does a table creation operation for MySQL. If the name of the created Drops a table for MySQL. If the name of the table ends in
table ends to characters INNODB_MONITOR, then this also starts one of "innodb_monitor", "innodb_lock_monitor", "innodb_tablespace_monitor",
printing of monitor output by the master thread. */ "innodb_table_monitor", then this will also start the printing of monitor
output by the master thread. If the table name ends in "innodb_mem_validate",
InnoDB will try to invoke mem_validate(). */
int int
row_create_table_for_mysql( row_create_table_for_mysql(
...@@ -399,8 +401,9 @@ row_truncate_table_for_mysql( ...@@ -399,8 +401,9 @@ row_truncate_table_for_mysql(
dict_table_t* table, /* in: table handle */ dict_table_t* table, /* in: table handle */
trx_t* trx); /* in: transaction handle */ trx_t* trx); /* in: transaction handle */
/************************************************************************* /*************************************************************************
Drops a table for MySQL. If the name of the dropped table ends to Drops a table for MySQL. If the name of the dropped table ends in
characters INNODB_MONITOR, then this also stops printing of monitor one of "innodb_monitor", "innodb_lock_monitor", "innodb_tablespace_monitor",
"innodb_table_monitor", then this will also stop the printing of monitor
output by the master thread. */ output by the master thread. */
int int
......
...@@ -101,6 +101,7 @@ void ...@@ -101,6 +101,7 @@ void
rw_lock_free( rw_lock_free(
/*=========*/ /*=========*/
rw_lock_t* lock); /* in: rw-lock */ rw_lock_t* lock); /* in: rw-lock */
#ifdef UNIV_DEBUG
/********************************************************************** /**********************************************************************
Checks that the rw-lock has been initialized and that there are no Checks that the rw-lock has been initialized and that there are no
simultaneous shared and exclusive locks. */ simultaneous shared and exclusive locks. */
...@@ -109,6 +110,7 @@ ibool ...@@ -109,6 +110,7 @@ ibool
rw_lock_validate( rw_lock_validate(
/*=============*/ /*=============*/
rw_lock_t* lock); rw_lock_t* lock);
#endif /* UNIV_DEBUG */
/****************************************************************** /******************************************************************
NOTE! The following macros should be used in rw s-locking, not the NOTE! The following macros should be used in rw s-locking, not the
corresponding function. */ corresponding function. */
......
...@@ -308,11 +308,39 @@ typedef void* os_thread_ret_t; ...@@ -308,11 +308,39 @@ typedef void* os_thread_ret_t;
# define UNIV_MEM_INVALID(addr, size) VALGRIND_MAKE_MEM_UNDEFINED(addr, size) # define UNIV_MEM_INVALID(addr, size) VALGRIND_MAKE_MEM_UNDEFINED(addr, size)
# define UNIV_MEM_FREE(addr, size) VALGRIND_MAKE_MEM_NOACCESS(addr, size) # define UNIV_MEM_FREE(addr, size) VALGRIND_MAKE_MEM_NOACCESS(addr, size)
# define UNIV_MEM_ALLOC(addr, size) VALGRIND_MAKE_MEM_UNDEFINED(addr, size) # define UNIV_MEM_ALLOC(addr, size) VALGRIND_MAKE_MEM_UNDEFINED(addr, size)
# define UNIV_MEM_ASSERT_RW(addr, size) do { \
const void* _p = (const void*) \
VALGRIND_CHECK_MEM_IS_DEFINED(addr, size); \
if (UNIV_LIKELY_NULL(_p)) \
fprintf(stderr, "%s:%d: %p[%u] undefined at %d\n", \
__FILE__, __LINE__, \
(const void*) (addr), (unsigned) (size), \
((const char*) _p) - ((const char*) (addr))); \
} while (0)
# define UNIV_MEM_ASSERT_W(addr, size) do { \
const void* _p = (const void*) \
VALGRIND_CHECK_MEM_IS_ADDRESSABLE(addr, size); \
if (UNIV_LIKELY_NULL(_p)) \
fprintf(stderr, "%s:%d: %p[%u] unwritable at %d\n", \
__FILE__, __LINE__, \
(const void*) (addr), (unsigned) (size), \
((const char*) _p) - ((const char*) (addr))); \
} while (0)
#else #else
# define UNIV_MEM_VALID(addr, size) do {} while(0) # define UNIV_MEM_VALID(addr, size) do {} while(0)
# define UNIV_MEM_INVALID(addr, size) do {} while(0) # define UNIV_MEM_INVALID(addr, size) do {} while(0)
# define UNIV_MEM_FREE(addr, size) do {} while(0) # define UNIV_MEM_FREE(addr, size) do {} while(0)
# define UNIV_MEM_ALLOC(addr, size) do {} while(0) # define UNIV_MEM_ALLOC(addr, size) do {} while(0)
# define UNIV_MEM_ASSERT_RW(addr, size) do {} while(0)
# define UNIV_MEM_ASSERT_W(addr, size) do {} while(0)
#endif #endif
#define UNIV_MEM_ASSERT_AND_FREE(addr, size) do { \
UNIV_MEM_ASSERT_W(addr, size); \
UNIV_MEM_FREE(addr, size); \
} while (0)
#define UNIV_MEM_ASSERT_AND_ALLOC(addr, size) do { \
UNIV_MEM_ASSERT_W(addr, size); \
UNIV_MEM_ALLOC(addr, size); \
} while (0)
#endif #endif
...@@ -263,6 +263,24 @@ ut_copy_file( ...@@ -263,6 +263,24 @@ ut_copy_file(
FILE* dest, /* in: output file */ FILE* dest, /* in: output file */
FILE* src); /* in: input file to be appended to output */ FILE* src); /* in: input file to be appended to output */
/**************************************************************************
snprintf(). */
#ifdef __WIN__
int
ut_snprintf(
/* out: number of characters that would
have been printed if the size were
unlimited, not including the terminating
'\0'. */
char* str, /* out: string */
size_t size, /* in: str size */
const char* fmt, /* in: format */
...); /* in: format values */
#else
#define ut_snprintf snprintf
#endif /* __WIN__ */
#ifndef UNIV_NONINL #ifndef UNIV_NONINL
#include "ut0ut.ic" #include "ut0ut.ic"
#endif #endif
......
...@@ -223,6 +223,8 @@ mem_init_buf( ...@@ -223,6 +223,8 @@ mem_init_buf(
{ {
byte* ptr; byte* ptr;
UNIV_MEM_ASSERT_W(buf, n);
for (ptr = buf; ptr < buf + n; ptr++) { for (ptr = buf; ptr < buf + n; ptr++) {
if (ut_rnd_gen_ibool()) { if (ut_rnd_gen_ibool()) {
...@@ -231,6 +233,8 @@ mem_init_buf( ...@@ -231,6 +233,8 @@ mem_init_buf(
*ptr = 0xBE; *ptr = 0xBE;
} }
} }
UNIV_MEM_INVALID(buf, n);
} }
/******************************************************************* /*******************************************************************
...@@ -245,6 +249,8 @@ mem_erase_buf( ...@@ -245,6 +249,8 @@ mem_erase_buf(
{ {
byte* ptr; byte* ptr;
UNIV_MEM_ASSERT_W(buf, n);
for (ptr = buf; ptr < buf + n; ptr++) { for (ptr = buf; ptr < buf + n; ptr++) {
if (ut_rnd_gen_ibool()) { if (ut_rnd_gen_ibool()) {
*ptr = 0xDE; *ptr = 0xDE;
...@@ -252,6 +258,8 @@ mem_erase_buf( ...@@ -252,6 +258,8 @@ mem_erase_buf(
*ptr = 0xAD; *ptr = 0xAD;
} }
} }
UNIV_MEM_FREE(buf, n);
} }
/******************************************************************* /*******************************************************************
...@@ -546,9 +554,7 @@ mem_heap_validate_or_print( ...@@ -546,9 +554,7 @@ mem_heap_validate_or_print(
} }
*error = FALSE; *error = FALSE;
} }
#endif /* UNIV_MEM_DEBUG || UNIV_DEBUG */
#ifdef UNIV_DEBUG
/****************************************************************** /******************************************************************
Prints the contents of a memory heap. */ Prints the contents of a memory heap. */
static static
...@@ -574,20 +580,6 @@ mem_heap_print( ...@@ -574,20 +580,6 @@ mem_heap_print(
ut_a(!error); ut_a(!error);
} }
/******************************************************************
Checks that an object is a memory heap (or a block of it). */
ibool
mem_heap_check(
/*===========*/
/* out: TRUE if ok */
mem_heap_t* heap) /* in: memory heap */
{
ut_a(heap->magic_n == MEM_BLOCK_MAGIC_N);
return(TRUE);
}
/****************************************************************** /******************************************************************
Validates the contents of a memory heap. */ Validates the contents of a memory heap. */
...@@ -614,6 +606,22 @@ mem_heap_validate( ...@@ -614,6 +606,22 @@ mem_heap_validate(
return(TRUE); return(TRUE);
} }
#endif /* UNIV_MEM_DEBUG || UNIV_DEBUG */
#ifdef UNIV_DEBUG
/******************************************************************
Checks that an object is a memory heap (or a block of it). */
ibool
mem_heap_check(
/*===========*/
/* out: TRUE if ok */
mem_heap_t* heap) /* in: memory heap */
{
ut_a(heap->magic_n == MEM_BLOCK_MAGIC_N);
return(TRUE);
}
#endif /* UNIV_DEBUG */ #endif /* UNIV_DEBUG */
#ifdef UNIV_MEM_DEBUG #ifdef UNIV_MEM_DEBUG
......
...@@ -512,9 +512,9 @@ mem_heap_block_free( ...@@ -512,9 +512,9 @@ mem_heap_block_free(
of hex 0xDE and 0xAD. */ of hex 0xDE and 0xAD. */
mem_erase_buf((byte*)block, len); mem_erase_buf((byte*)block, len);
#else /* UNIV_MEM_DEBUG */
#endif UNIV_MEM_ASSERT_AND_FREE(block, len);
UNIV_MEM_FREE(block, len); #endif /* UNIV_MEM_DEBUG */
if (init_block) { if (init_block) {
/* Do not have to free: do nothing */ /* Do not have to free: do nothing */
......
...@@ -1728,10 +1728,11 @@ row_mysql_unlock_data_dictionary( ...@@ -1728,10 +1728,11 @@ row_mysql_unlock_data_dictionary(
} }
/************************************************************************* /*************************************************************************
Does a table creation operation for MySQL. If the name of the table Drops a table for MySQL. If the name of the table ends in
to be created is equal with one of the predefined magic table names, one of "innodb_monitor", "innodb_lock_monitor", "innodb_tablespace_monitor",
then this also starts printing the corresponding monitor output by "innodb_table_monitor", then this will also start the printing of monitor
the master thread. */ output by the master thread. If the table name ends in "innodb_mem_validate",
InnoDB will try to invoke mem_validate(). */
int int
row_create_table_for_mysql( row_create_table_for_mysql(
...@@ -1756,13 +1757,11 @@ row_create_table_for_mysql( ...@@ -1756,13 +1757,11 @@ row_create_table_for_mysql(
ut_ad(trx->dict_operation_lock_mode == RW_X_LATCH); ut_ad(trx->dict_operation_lock_mode == RW_X_LATCH);
if (srv_created_new_raw) { if (srv_created_new_raw) {
fputs("InnoDB: A new raw disk partition was initialized or\n" fputs("InnoDB: A new raw disk partition was initialized:\n"
"InnoDB: innodb_force_recovery is on: we do not allow\n" "InnoDB: we do not allow database modifications"
"InnoDB: database modifications by the user. Shut down\n" " by the user.\n"
"InnoDB: mysqld and edit my.cnf so that newraw" "InnoDB: Shut down mysqld and edit my.cnf so that newraw"
" is replaced\n" " is replaced with raw.\n", stderr);
"InnoDB: with raw, and innodb_force_... is removed.\n",
stderr);
dict_mem_table_free(table); dict_mem_table_free(table);
trx_commit_for_mysql(trx); trx_commit_for_mysql(trx);
...@@ -2703,13 +2702,11 @@ row_truncate_table_for_mysql( ...@@ -2703,13 +2702,11 @@ row_truncate_table_for_mysql(
ut_ad(table); ut_ad(table);
if (srv_created_new_raw) { if (srv_created_new_raw) {
fputs("InnoDB: A new raw disk partition was initialized or\n" fputs("InnoDB: A new raw disk partition was initialized:\n"
"InnoDB: innodb_force_recovery is on: we do not allow\n" "InnoDB: we do not allow database modifications"
"InnoDB: database modifications by the user. Shut down\n" " by the user.\n"
"InnoDB: mysqld and edit my.cnf so that newraw" "InnoDB: Shut down mysqld and edit my.cnf so that newraw"
" is replaced\n" " is replaced with raw.\n", stderr);
"InnoDB: with raw, and innodb_force_... is removed.\n",
stderr);
return(DB_ERROR); return(DB_ERROR);
} }
...@@ -2898,7 +2895,9 @@ row_truncate_table_for_mysql( ...@@ -2898,7 +2895,9 @@ row_truncate_table_for_mysql(
/* MySQL calls ha_innobase::reset_auto_increment() which does /* MySQL calls ha_innobase::reset_auto_increment() which does
the same thing. */ the same thing. */
dict_table_autoinc_lock(table);
dict_table_autoinc_initialize(table, 0); dict_table_autoinc_initialize(table, 0);
dict_table_autoinc_unlock(table);
dict_update_statistics(table); dict_update_statistics(table);
trx_commit_for_mysql(trx); trx_commit_for_mysql(trx);
...@@ -2916,9 +2915,10 @@ row_truncate_table_for_mysql( ...@@ -2916,9 +2915,10 @@ row_truncate_table_for_mysql(
#endif /* !UNIV_HOTBACKUP */ #endif /* !UNIV_HOTBACKUP */
/************************************************************************* /*************************************************************************
Drops a table for MySQL. If the name of the table to be dropped is equal Drops a table for MySQL. If the name of the dropped table ends in
with one of the predefined magic table names, then this also stops printing one of "innodb_monitor", "innodb_lock_monitor", "innodb_tablespace_monitor",
the corresponding monitor output by the master thread. */ "innodb_table_monitor", then this will also stop the printing of monitor
output by the master thread. */
int int
row_drop_table_for_mysql( row_drop_table_for_mysql(
...@@ -2934,21 +2934,17 @@ row_drop_table_for_mysql( ...@@ -2934,21 +2934,17 @@ row_drop_table_for_mysql(
ulint err; ulint err;
const char* table_name; const char* table_name;
ulint namelen; ulint namelen;
char* dir_path_of_temp_table = NULL;
ibool success;
ibool locked_dictionary = FALSE; ibool locked_dictionary = FALSE;
pars_info_t* info = NULL; pars_info_t* info = NULL;
ut_a(name != NULL); ut_a(name != NULL);
if (srv_created_new_raw) { if (srv_created_new_raw) {
fputs("InnoDB: A new raw disk partition was initialized or\n" fputs("InnoDB: A new raw disk partition was initialized:\n"
"InnoDB: innodb_force_recovery is on: we do not allow\n" "InnoDB: we do not allow database modifications"
"InnoDB: database modifications by the user. Shut down\n" " by the user.\n"
"InnoDB: mysqld and edit my.cnf so that newraw" "InnoDB: Shut down mysqld and edit my.cnf so that newraw"
" is replaced\n" " is replaced with raw.\n", stderr);
"InnoDB: with raw, and innodb_force_... is removed.\n",
stderr);
return(DB_ERROR); return(DB_ERROR);
} }
...@@ -3232,14 +3228,20 @@ row_drop_table_for_mysql( ...@@ -3232,14 +3228,20 @@ row_drop_table_for_mysql(
} else { } else {
ibool is_path; ibool is_path;
const char* name_or_path; const char* name_or_path;
mem_heap_t* heap;
heap = mem_heap_create(200);
/* Clone the name, in case it has been allocated
from table->heap, which will be freed by
dict_table_remove_from_cache(table) below. */
name = mem_heap_strdup(heap, name);
space_id = table->space; space_id = table->space;
if (table->dir_path_of_temp_table != NULL) { if (table->dir_path_of_temp_table != NULL) {
dir_path_of_temp_table = mem_strdup(
table->dir_path_of_temp_table);
is_path = TRUE; is_path = TRUE;
name_or_path = dir_path_of_temp_table; name_or_path = mem_heap_strdup(
heap, table->dir_path_of_temp_table);
} else { } else {
is_path = FALSE; is_path = FALSE;
name_or_path = name; name_or_path = name;
...@@ -3272,13 +3274,7 @@ row_drop_table_for_mysql( ...@@ -3272,13 +3274,7 @@ row_drop_table_for_mysql(
"InnoDB: of table "); "InnoDB: of table ");
ut_print_name(stderr, trx, TRUE, name); ut_print_name(stderr, trx, TRUE, name);
fprintf(stderr, ".\n"); fprintf(stderr, ".\n");
} else if (!fil_delete_tablespace(space_id)) {
goto funct_exit;
}
success = fil_delete_tablespace(space_id);
if (!success) {
fprintf(stderr, fprintf(stderr,
"InnoDB: We removed now the InnoDB" "InnoDB: We removed now the InnoDB"
" internal data dictionary entry\n" " internal data dictionary entry\n"
...@@ -3296,6 +3292,8 @@ row_drop_table_for_mysql( ...@@ -3296,6 +3292,8 @@ row_drop_table_for_mysql(
err = DB_ERROR; err = DB_ERROR;
} }
} }
mem_heap_free(heap);
} }
funct_exit: funct_exit:
...@@ -3305,10 +3303,6 @@ row_drop_table_for_mysql( ...@@ -3305,10 +3303,6 @@ row_drop_table_for_mysql(
row_mysql_unlock_data_dictionary(trx); row_mysql_unlock_data_dictionary(trx);
} }
if (dir_path_of_temp_table) {
mem_free(dir_path_of_temp_table);
}
trx->op_info = ""; trx->op_info = "";
#ifndef UNIV_HOTBACKUP #ifndef UNIV_HOTBACKUP
......
...@@ -531,12 +531,13 @@ row_sel_build_prev_vers( ...@@ -531,12 +531,13 @@ row_sel_build_prev_vers(
/*====================*/ /*====================*/
/* out: DB_SUCCESS or error code */ /* out: DB_SUCCESS or error code */
read_view_t* read_view, /* in: read view */ read_view_t* read_view, /* in: read view */
plan_t* plan, /* in: plan node for table */ dict_index_t* index, /* in: plan node for table */
rec_t* rec, /* in: record in a clustered index */ rec_t* rec, /* in: record in a clustered index */
ulint** offsets, /* in/out: offsets returned by ulint** offsets, /* in/out: offsets returned by
rec_get_offsets(rec, plan->index) */ rec_get_offsets(rec, plan->index) */
mem_heap_t** offset_heap, /* in/out: memory heap from which mem_heap_t** offset_heap, /* in/out: memory heap from which
the offsets are allocated */ the offsets are allocated */
mem_heap_t** old_vers_heap, /* out: old version heap to use */
rec_t** old_vers, /* out: old version, or NULL if the rec_t** old_vers, /* out: old version, or NULL if the
record does not exist in the view: record does not exist in the view:
i.e., it was freshly inserted i.e., it was freshly inserted
...@@ -545,15 +546,15 @@ row_sel_build_prev_vers( ...@@ -545,15 +546,15 @@ row_sel_build_prev_vers(
{ {
ulint err; ulint err;
if (plan->old_vers_heap) { if (*old_vers_heap) {
mem_heap_empty(plan->old_vers_heap); mem_heap_empty(*old_vers_heap);
} else { } else {
plan->old_vers_heap = mem_heap_create(512); *old_vers_heap = mem_heap_create(512);
} }
err = row_vers_build_for_consistent_read( err = row_vers_build_for_consistent_read(
rec, mtr, plan->index, offsets, read_view, offset_heap, rec, mtr, index, offsets, read_view, offset_heap,
plan->old_vers_heap, old_vers); *old_vers_heap, old_vers);
return(err); return(err);
} }
...@@ -765,9 +766,11 @@ row_sel_get_clust_rec( ...@@ -765,9 +766,11 @@ row_sel_get_clust_rec(
if (!lock_clust_rec_cons_read_sees(clust_rec, index, offsets, if (!lock_clust_rec_cons_read_sees(clust_rec, index, offsets,
node->read_view)) { node->read_view)) {
err = row_sel_build_prev_vers(node->read_view, plan, err = row_sel_build_prev_vers(
clust_rec, &offsets, node->read_view, index, clust_rec,
&heap, &old_vers, mtr); &offsets, &heap, &plan->old_vers_heap,
&old_vers, mtr);
if (err != DB_SUCCESS) { if (err != DB_SUCCESS) {
goto err_exit; goto err_exit;
...@@ -1490,10 +1493,11 @@ row_sel( ...@@ -1490,10 +1493,11 @@ row_sel(
if (!lock_clust_rec_cons_read_sees(rec, index, offsets, if (!lock_clust_rec_cons_read_sees(rec, index, offsets,
node->read_view)) { node->read_view)) {
err = row_sel_build_prev_vers(node->read_view, err = row_sel_build_prev_vers(
plan, rec, node->read_view, index, rec,
&offsets, &heap, &offsets, &heap, &plan->old_vers_heap,
&old_vers, &mtr); &old_vers, &mtr);
if (err != DB_SUCCESS) { if (err != DB_SUCCESS) {
goto lock_wait_or_error; goto lock_wait_or_error;
...@@ -3999,6 +4003,7 @@ row_search_for_mysql( ...@@ -3999,6 +4003,7 @@ row_search_for_mysql(
mutex_enter(&kernel_mutex); mutex_enter(&kernel_mutex);
if (trx->was_chosen_as_deadlock_victim) { if (trx->was_chosen_as_deadlock_victim) {
mutex_exit(&kernel_mutex); mutex_exit(&kernel_mutex);
err = DB_DEADLOCK;
goto lock_wait_or_error; goto lock_wait_or_error;
} }
...@@ -4536,6 +4541,7 @@ row_search_autoinc_read_column( ...@@ -4536,6 +4541,7 @@ row_search_autoinc_read_column(
const byte* data; const byte* data;
ib_longlong value; ib_longlong value;
mem_heap_t* heap = NULL; mem_heap_t* heap = NULL;
/* Our requirement is that dest should be word aligned. */
byte dest[sizeof(value)]; byte dest[sizeof(value)];
ulint offsets_[REC_OFFS_NORMAL_SIZE]; ulint offsets_[REC_OFFS_NORMAL_SIZE];
ulint* offsets = offsets_; ulint* offsets = offsets_;
...@@ -4554,20 +4560,35 @@ row_search_autoinc_read_column( ...@@ -4554,20 +4560,35 @@ row_search_autoinc_read_column(
ut_a(len != UNIV_SQL_NULL); ut_a(len != UNIV_SQL_NULL);
ut_a(len <= sizeof value); ut_a(len <= sizeof value);
/* Copy integer data and restore sign bit */ mach_read_int_type(dest, data, len, unsigned_type);
if (unsigned_type || (data[0] & 128))
memset(dest, 0x00, sizeof(dest)); /* The assumption here is that the AUTOINC value can't be negative
else and that dest is word aligned. */
memset(dest, 0xff, sizeof(dest)); switch (len) {
case 8:
value = *(ib_longlong*) dest;
break;
memcpy(dest + (sizeof(value) - len), data, len); case 4:
value = *(ib_uint32_t*) dest;
break;
if (!unsigned_type) case 3:
dest[sizeof(value) - len] ^= 128; value = *(ib_uint32_t*) dest;
value &= 0xFFFFFF;
break;
/* The assumption here is that the AUTOINC value can't be negative.*/ case 2:
value = (((ib_longlong) mach_read_from_4(dest)) << 32) | value = *(uint16 *) dest;
((ib_longlong) mach_read_from_4(dest + 4)); break;
case 1:
value = *dest;
break;
default:
ut_error;
}
if (UNIV_LIKELY_NULL(heap)) { if (UNIV_LIKELY_NULL(heap)) {
mem_heap_free(heap); mem_heap_free(heap);
......
...@@ -174,9 +174,7 @@ rw_lock_free( ...@@ -174,9 +174,7 @@ rw_lock_free(
/*=========*/ /*=========*/
rw_lock_t* lock) /* in: rw-lock */ rw_lock_t* lock) /* in: rw-lock */
{ {
#ifdef UNIV_DEBUG ut_ad(rw_lock_validate(lock));
ut_a(rw_lock_validate(lock));
#endif /* UNIV_DEBUG */
ut_a(rw_lock_get_writer(lock) == RW_LOCK_NOT_LOCKED); ut_a(rw_lock_get_writer(lock) == RW_LOCK_NOT_LOCKED);
ut_a(rw_lock_get_waiters(lock) == 0); ut_a(rw_lock_get_waiters(lock) == 0);
ut_a(rw_lock_get_reader_count(lock) == 0); ut_a(rw_lock_get_reader_count(lock) == 0);
...@@ -199,6 +197,7 @@ rw_lock_free( ...@@ -199,6 +197,7 @@ rw_lock_free(
mutex_exit(&rw_lock_list_mutex); mutex_exit(&rw_lock_list_mutex);
} }
#ifdef UNIV_DEBUG
/********************************************************************** /**********************************************************************
Checks that the rw-lock has been initialized and that there are no Checks that the rw-lock has been initialized and that there are no
simultaneous shared and exclusive locks. */ simultaneous shared and exclusive locks. */
...@@ -226,6 +225,7 @@ rw_lock_validate( ...@@ -226,6 +225,7 @@ rw_lock_validate(
return(TRUE); return(TRUE);
} }
#endif /* UNIV_DEBUG */
/********************************************************************** /**********************************************************************
Lock an rw-lock in shared mode for the current thread. If the rw-lock is Lock an rw-lock in shared mode for the current thread. If the rw-lock is
......
...@@ -18,6 +18,7 @@ Created 5/11/1994 Heikki Tuuri ...@@ -18,6 +18,7 @@ Created 5/11/1994 Heikki Tuuri
#include "ut0sort.h" #include "ut0sort.h"
#include "trx0trx.h" #include "trx0trx.h"
#include "ha_prototypes.h"
ibool ut_always_false = FALSE; ibool ut_always_false = FALSE;
...@@ -70,22 +71,6 @@ ut_gettimeofday( ...@@ -70,22 +71,6 @@ ut_gettimeofday(
#define ut_gettimeofday gettimeofday #define ut_gettimeofday gettimeofday
#endif #endif
#ifndef UNIV_HOTBACKUP
/*********************************************************************
Display an SQL identifier.
This definition must match the one in sql/ha_innodb.cc! */
extern
void
innobase_print_identifier(
/*======================*/
FILE* f, /* in: output stream */
trx_t* trx, /* in: transaction */
ibool table_id,/* in: TRUE=print a table name,
FALSE=print other identifier */
const char* name, /* in: name to print */
ulint namelen);/* in: length of name */
#endif /* !UNIV_HOTBACKUP */
/************************************************************ /************************************************************
Gets the high 32 bits in a ulint. That is makes a shift >> 32, Gets the high 32 bits in a ulint. That is makes a shift >> 32,
but since there seem to be compiler bugs in both gcc and Visual C++, but since there seem to be compiler bugs in both gcc and Visual C++,
...@@ -360,6 +345,8 @@ ut_print_buf( ...@@ -360,6 +345,8 @@ ut_print_buf(
const byte* data; const byte* data;
ulint i; ulint i;
UNIV_MEM_ASSERT_RW(buf, len);
fprintf(file, " len %lu; hex ", len); fprintf(file, " len %lu; hex ", len);
for (data = (const byte*)buf, i = 0; i < len; i++) { for (data = (const byte*)buf, i = 0; i < len; i++) {
...@@ -474,17 +461,20 @@ ut_print_namel( ...@@ -474,17 +461,20 @@ ut_print_namel(
#ifdef UNIV_HOTBACKUP #ifdef UNIV_HOTBACKUP
fwrite(name, 1, namelen, f); fwrite(name, 1, namelen, f);
#else #else
char* slash = memchr(name, '/', namelen); if (table_id) {
char* slash = memchr(name, '/', namelen);
if (!slash) {
if (UNIV_LIKELY_NULL(slash)) { goto no_db_name;
/* Print the database name and table name separately. */ }
ut_ad(table_id);
/* Print the database name and table name separately. */
innobase_print_identifier(f, trx, TRUE, name, slash - name); innobase_print_identifier(f, trx, TRUE, name, slash - name);
putc('.', f); putc('.', f);
innobase_print_identifier(f, trx, TRUE, slash + 1, innobase_print_identifier(f, trx, TRUE, slash + 1,
namelen - (slash - name) - 1); namelen - (slash - name) - 1);
} else { } else {
no_db_name:
innobase_print_identifier(f, trx, table_id, name, namelen); innobase_print_identifier(f, trx, table_id, name, namelen);
} }
#endif #endif
...@@ -515,3 +505,44 @@ ut_copy_file( ...@@ -515,3 +505,44 @@ ut_copy_file(
} }
} while (len > 0); } while (len > 0);
} }
/**************************************************************************
snprintf(). */
#ifdef __WIN__
#include <stdarg.h>
int
ut_snprintf(
/* out: number of characters that would
have been printed if the size were
unlimited, not including the terminating
'\0'. */
char* str, /* out: string */
size_t size, /* in: str size */
const char* fmt, /* in: format */
...) /* in: format values */
{
int res;
va_list ap1;
va_list ap2;
va_start(ap1, fmt);
va_start(ap2, fmt);
res = _vscprintf(fmt, ap1);
ut_a(res != -1);
if (size > 0) {
_vsnprintf(str, size, fmt, ap2);
if ((size_t) res >= size) {
str[size - 1] = '\0';
}
}
va_end(ap1);
va_end(ap2);
return(res);
}
#endif /* __WIN__ */
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment