mirror of
https://github.com/MariaDB/server.git
synced 2025-07-30 16:24:05 +03:00
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
This commit is contained in:
36
mysql-test/r/innodb-semi-consistent.result
Normal file
36
mysql-test/r/innodb-semi-consistent.result
Normal file
@ -0,0 +1,36 @@
|
|||||||
|
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
|
|||||||
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
|
|||||||
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),
|
|||||||
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;
|
||||||
|
39
mysql-test/r/innodb_autoinc_lock_mode_zero.result
Normal file
39
mysql-test/r/innodb_autoinc_lock_mode_zero.result
Normal file
@ -0,0 +1,39 @@
|
|||||||
|
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
|
1
mysql-test/t/innodb-semi-consistent-master.opt
Normal file
1
mysql-test/t/innodb-semi-consistent-master.opt
Normal file
@ -0,0 +1 @@
|
|||||||
|
--innodb_locks_unsafe_for_binlog=true --innodb_lock_wait_timeout=2
|
46
mysql-test/t/innodb-semi-consistent.test
Normal file
46
mysql-test/t/innodb-semi-consistent.test
Normal file
@ -0,0 +1,46 @@
|
|||||||
|
-- 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;
|
|||||||
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 (
|
|||||||
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. #
|
||||||
|
1
mysql-test/t/innodb_autoinc_lock_mode_zero-master.opt
Normal file
1
mysql-test/t/innodb_autoinc_lock_mode_zero-master.opt
Normal file
@ -0,0 +1 @@
|
|||||||
|
--innodb-autoinc-lock-mode=0
|
44
mysql-test/t/innodb_autoinc_lock_mode_zero.test
Normal file
44
mysql-test/t/innodb_autoinc_lock_mode_zero.test
Normal file
@ -0,0 +1,44 @@
|
|||||||
|
# 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(
|
|||||||
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(
|
|||||||
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(
|
|||||||
{
|
{
|
||||||
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(
|
|||||||
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(
|
|||||||
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(
|
|||||||
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(
|
|||||||
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(
|
|||||||
"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(
|
|||||||
" 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(
|
|||||||
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 @@ err_exit:
|
|||||||
|
|
||||||
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;
|
|||||||
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(
|
|||||||
}
|
}
|
||||||
|
|
||||||
/*********************************************************************
|
/*********************************************************************
|
||||||
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(
|
|||||||
|
|
||||||
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(
|
|||||||
|
|
||||||
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 @@ no_commit:
|
|||||||
|
|
||||||
/* 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 @@ set_max_autoinc:
|
|||||||
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(
|
|||||||
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(
|
|||||||
|
|
||||||
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(
|
|||||||
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(
|
|||||||
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. */
|
|||||||
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(
|
|||||||
++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(
|
|||||||
{
|
{
|
||||||
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(
|
|||||||
} 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.
|
|||||||
|
|
||||||
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(
|
|||||||
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(
|
|||||||
|
|
||||||
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(
|
|||||||
/* 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(
|
|||||||
|
|
||||||
/* 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,
|
|||||||
"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[]= {
|
|||||||
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);
|
|||||||
*/
|
*/
|
||||||
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 @@ dump:
|
|||||||
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 @@ dump:
|
|||||||
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
|
|||||||
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
|
||||||
|
@ -1,6 +1,8 @@
|
|||||||
#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(
|
|||||||
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(
|
|||||||
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(
|
|||||||
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.
|
|||||||
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(
|
|||||||
|
|
||||||
*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(
|
|||||||
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(
|
|||||||
/* 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(
|
|||||||
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(
|
|||||||
/* 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(
|
|||||||
== 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(
|
|||||||
{
|
{
|
||||||
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(
|
|||||||
/*===============================*/
|
/*===============================*/
|
||||||
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(
|
|||||||
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
|
|||||||
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
|
|||||||
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;
|
|||||||
# 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(
|
|||||||
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(
|
|||||||
{
|
{
|
||||||
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(
|
|||||||
*ptr = 0xBE;
|
*ptr = 0xBE;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
UNIV_MEM_INVALID(buf, n);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*******************************************************************
|
/*******************************************************************
|
||||||
@ -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(
|
|||||||
*ptr = 0xAD;
|
*ptr = 0xAD;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
UNIV_MEM_FREE(buf, n);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*******************************************************************
|
/*******************************************************************
|
||||||
@ -546,9 +554,7 @@ completed:
|
|||||||
}
|
}
|
||||||
*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(
|
|||||||
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(
|
|||||||
|
|
||||||
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(
|
|||||||
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(
|
|||||||
}
|
}
|
||||||
|
|
||||||
/*************************************************************************
|
/*************************************************************************
|
||||||
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(
|
|||||||
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(
|
|||||||
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 @@ next_rec:
|
|||||||
|
|
||||||
/* 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 @@ funct_exit:
|
|||||||
#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(
|
|||||||
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 @@ check_next_foreign:
|
|||||||
} 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 @@ check_next_foreign:
|
|||||||
"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 @@ check_next_foreign:
|
|||||||
err = DB_ERROR;
|
err = DB_ERROR;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
mem_heap_free(heap);
|
||||||
}
|
}
|
||||||
funct_exit:
|
funct_exit:
|
||||||
|
|
||||||
@ -3305,10 +3303,6 @@ funct_exit:
|
|||||||
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(
|
|||||||
/*====================*/
|
/*====================*/
|
||||||
/* 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(
|
|||||||
{
|
{
|
||||||
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(
|
|||||||
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 @@ skip_lock:
|
|||||||
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 @@ no_gap_lock:
|
|||||||
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(
|
|||||||
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(
|
|||||||
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));
|
|
||||||
else
|
|
||||||
memset(dest, 0xff, sizeof(dest));
|
|
||||||
|
|
||||||
memcpy(dest + (sizeof(value) - len), data, len);
|
/* The assumption here is that the AUTOINC value can't be negative
|
||||||
|
and that dest is word aligned. */
|
||||||
|
switch (len) {
|
||||||
|
case 8:
|
||||||
|
value = *(ib_longlong*) dest;
|
||||||
|
break;
|
||||||
|
|
||||||
if (!unsigned_type)
|
case 4:
|
||||||
dest[sizeof(value) - len] ^= 128;
|
value = *(ib_uint32_t*) dest;
|
||||||
|
break;
|
||||||
|
|
||||||
/* The assumption here is that the AUTOINC value can't be negative.*/
|
case 3:
|
||||||
value = (((ib_longlong) mach_read_from_4(dest)) << 32) |
|
value = *(ib_uint32_t*) dest;
|
||||||
((ib_longlong) mach_read_from_4(dest + 4));
|
value &= 0xFFFFFF;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 2:
|
||||||
|
value = *(uint16 *) dest;
|
||||||
|
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(
|
|||||||
/*=========*/
|
/*=========*/
|
||||||
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(
|
|||||||
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(
|
|||||||
|
|
||||||
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
|
|||||||
|
|
||||||
#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(
|
|||||||
#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(
|
|||||||
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(
|
|||||||
#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) {
|
||||||
|
|
||||||
|
goto no_db_name;
|
||||||
|
}
|
||||||
|
|
||||||
if (UNIV_LIKELY_NULL(slash)) {
|
|
||||||
/* Print the database name and table name separately. */
|
/* Print the database name and table name separately. */
|
||||||
ut_ad(table_id);
|
|
||||||
|
|
||||||
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(
|
|||||||
}
|
}
|
||||||
} 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__ */
|
||||||
|
Reference in New Issue
Block a user