mirror of
https://github.com/MariaDB/server.git
synced 2025-08-01 03:47:19 +03:00
Merge mysql-5.1 to mysql-5.5.
This commit is contained in:
119
mysql-test/suite/innodb/r/innodb-blob.result
Normal file
119
mysql-test/suite/innodb/r/innodb-blob.result
Normal file
@ -0,0 +1,119 @@
|
|||||||
|
CREATE TABLE t1 (a INT PRIMARY KEY, b TEXT) ENGINE=InnoDB;
|
||||||
|
CREATE TABLE t2 (a INT PRIMARY KEY) ENGINE=InnoDB;
|
||||||
|
CREATE TABLE t3 (a INT PRIMARY KEY, b TEXT, c TEXT) ENGINE=InnoDB;
|
||||||
|
INSERT INTO t1 VALUES (1,REPEAT('a',30000)),(2,REPEAT('b',40000));
|
||||||
|
SET DEBUG_SYNC='before_row_upd_extern SIGNAL have_latch WAIT_FOR go1';
|
||||||
|
BEGIN;
|
||||||
|
UPDATE t1 SET a=a+2;
|
||||||
|
ROLLBACK;
|
||||||
|
BEGIN;
|
||||||
|
UPDATE t1 SET b=CONCAT(b,'foo');
|
||||||
|
SET DEBUG_SYNC='now WAIT_FOR have_latch';
|
||||||
|
SELECT a, RIGHT(b,20) FROM t1;
|
||||||
|
SET DEBUG_SYNC='now SIGNAL go1';
|
||||||
|
a RIGHT(b,20)
|
||||||
|
1 aaaaaaaaaaaaaaaaaaaa
|
||||||
|
2 bbbbbbbbbbbbbbbbbbbb
|
||||||
|
SET DEBUG='+d,row_ins_extern_checkpoint';
|
||||||
|
SET DEBUG_SYNC='before_row_ins_extern_latch SIGNAL rec_not_blob WAIT_FOR crash';
|
||||||
|
ROLLBACK;
|
||||||
|
BEGIN;
|
||||||
|
INSERT INTO t1 VALUES (3,REPEAT('c',50000));
|
||||||
|
SET DEBUG_SYNC='now WAIT_FOR rec_not_blob';
|
||||||
|
SET SESSION TRANSACTION ISOLATION LEVEL READ UNCOMMITTED;
|
||||||
|
SELECT @@tx_isolation;
|
||||||
|
@@tx_isolation
|
||||||
|
READ-UNCOMMITTED
|
||||||
|
SELECT a, RIGHT(b,20) FROM t1;
|
||||||
|
a RIGHT(b,20)
|
||||||
|
1 aaaaaaaaaaaaaaaaaaaa
|
||||||
|
2 bbbbbbbbbbbbbbbbbbbb
|
||||||
|
SELECT a FROM t1;
|
||||||
|
a
|
||||||
|
1
|
||||||
|
2
|
||||||
|
3
|
||||||
|
SET DEBUG='+d,crash_commit_before';
|
||||||
|
INSERT INTO t2 VALUES (42);
|
||||||
|
ERROR HY000: Lost connection to MySQL server during query
|
||||||
|
ERROR HY000: Lost connection to MySQL server during query
|
||||||
|
CHECK TABLE t1;
|
||||||
|
Table Op Msg_type Msg_text
|
||||||
|
test.t1 check status OK
|
||||||
|
INSERT INTO t3 VALUES
|
||||||
|
(1,REPEAT('d',7000),REPEAT('e',100)),
|
||||||
|
(2,REPEAT('g',7000),REPEAT('h',100));
|
||||||
|
SET DEBUG_SYNC='before_row_upd_extern SIGNAL have_latch WAIT_FOR go';
|
||||||
|
UPDATE t3 SET c=REPEAT('f',3000) WHERE a=1;
|
||||||
|
SET DEBUG_SYNC='now WAIT_FOR have_latch';
|
||||||
|
SET SESSION TRANSACTION ISOLATION LEVEL READ UNCOMMITTED;
|
||||||
|
SELECT @@tx_isolation;
|
||||||
|
@@tx_isolation
|
||||||
|
READ-UNCOMMITTED
|
||||||
|
SELECT a, RIGHT(b,20), RIGHT(c,20) FROM t3;
|
||||||
|
SET DEBUG_SYNC='now SIGNAL go';
|
||||||
|
a RIGHT(b,20) RIGHT(c,20)
|
||||||
|
1 dddddddddddddddddddd ffffffffffffffffffff
|
||||||
|
2 gggggggggggggggggggg hhhhhhhhhhhhhhhhhhhh
|
||||||
|
CHECK TABLE t1,t2,t3;
|
||||||
|
Table Op Msg_type Msg_text
|
||||||
|
test.t1 check status OK
|
||||||
|
test.t2 check status OK
|
||||||
|
test.t3 check status OK
|
||||||
|
BEGIN;
|
||||||
|
INSERT INTO t2 VALUES (347);
|
||||||
|
SET DEBUG='+d,row_upd_extern_checkpoint';
|
||||||
|
SET DEBUG_SYNC='before_row_upd_extern SIGNAL have_latch WAIT_FOR crash';
|
||||||
|
UPDATE t3 SET c=REPEAT('i',3000) WHERE a=2;
|
||||||
|
SET DEBUG_SYNC='now WAIT_FOR have_latch';
|
||||||
|
SELECT info FROM information_schema.processlist
|
||||||
|
WHERE state = 'debug sync point: before_row_upd_extern';
|
||||||
|
info
|
||||||
|
UPDATE t3 SET c=REPEAT('i',3000) WHERE a=2
|
||||||
|
SET DEBUG='+d,crash_commit_before';
|
||||||
|
COMMIT;
|
||||||
|
ERROR HY000: Lost connection to MySQL server during query
|
||||||
|
ERROR HY000: Lost connection to MySQL server during query
|
||||||
|
CHECK TABLE t1,t2,t3;
|
||||||
|
Table Op Msg_type Msg_text
|
||||||
|
test.t1 check status OK
|
||||||
|
test.t2 check status OK
|
||||||
|
test.t3 check status OK
|
||||||
|
SELECT a, RIGHT(b,20), RIGHT(c,20) FROM t3;
|
||||||
|
a RIGHT(b,20) RIGHT(c,20)
|
||||||
|
1 dddddddddddddddddddd ffffffffffffffffffff
|
||||||
|
2 gggggggggggggggggggg hhhhhhhhhhhhhhhhhhhh
|
||||||
|
SELECT a FROM t3;
|
||||||
|
a
|
||||||
|
1
|
||||||
|
2
|
||||||
|
BEGIN;
|
||||||
|
INSERT INTO t2 VALUES (33101);
|
||||||
|
SET DEBUG='+d,row_upd_extern_checkpoint';
|
||||||
|
SET DEBUG_SYNC='after_row_upd_extern SIGNAL have_latch WAIT_FOR crash';
|
||||||
|
UPDATE t3 SET c=REPEAT('j',3000) WHERE a=2;
|
||||||
|
SET DEBUG_SYNC='now WAIT_FOR have_latch';
|
||||||
|
SELECT info FROM information_schema.processlist
|
||||||
|
WHERE state = 'debug sync point: after_row_upd_extern';
|
||||||
|
info
|
||||||
|
UPDATE t3 SET c=REPEAT('j',3000) WHERE a=2
|
||||||
|
SET DEBUG='+d,crash_commit_before';
|
||||||
|
COMMIT;
|
||||||
|
ERROR HY000: Lost connection to MySQL server during query
|
||||||
|
ERROR HY000: Lost connection to MySQL server during query
|
||||||
|
CHECK TABLE t1,t2,t3;
|
||||||
|
Table Op Msg_type Msg_text
|
||||||
|
test.t1 check status OK
|
||||||
|
test.t2 check status OK
|
||||||
|
test.t3 check status OK
|
||||||
|
SELECT a, RIGHT(b,20), RIGHT(c,20) FROM t3;
|
||||||
|
a RIGHT(b,20) RIGHT(c,20)
|
||||||
|
1 dddddddddddddddddddd ffffffffffffffffffff
|
||||||
|
2 gggggggggggggggggggg hhhhhhhhhhhhhhhhhhhh
|
||||||
|
SELECT a FROM t3;
|
||||||
|
a
|
||||||
|
1
|
||||||
|
2
|
||||||
|
SELECT * FROM t2;
|
||||||
|
a
|
||||||
|
DROP TABLE t1,t2,t3;
|
216
mysql-test/suite/innodb/t/innodb-blob.test
Normal file
216
mysql-test/suite/innodb/t/innodb-blob.test
Normal file
@ -0,0 +1,216 @@
|
|||||||
|
# Bug#13721257 RACE CONDITION IN UPDATES OR INSERTS OF WIDE RECORDS
|
||||||
|
# Test what happens when a record is inserted or updated so that some
|
||||||
|
# columns are stored off-page.
|
||||||
|
|
||||||
|
--source include/have_innodb.inc
|
||||||
|
|
||||||
|
# DEBUG_SYNC must be compiled in.
|
||||||
|
--source include/have_debug_sync.inc
|
||||||
|
|
||||||
|
# Valgrind would complain about memory leaks when we crash on purpose.
|
||||||
|
--source include/not_valgrind.inc
|
||||||
|
# Embedded server does not support crashing
|
||||||
|
--source include/not_embedded.inc
|
||||||
|
# Avoid CrashReporter popup on Mac
|
||||||
|
--source include/not_crashrep.inc
|
||||||
|
|
||||||
|
CREATE TABLE t1 (a INT PRIMARY KEY, b TEXT) ENGINE=InnoDB;
|
||||||
|
CREATE TABLE t2 (a INT PRIMARY KEY) ENGINE=InnoDB;
|
||||||
|
CREATE TABLE t3 (a INT PRIMARY KEY, b TEXT, c TEXT) ENGINE=InnoDB;
|
||||||
|
|
||||||
|
INSERT INTO t1 VALUES (1,REPEAT('a',30000)),(2,REPEAT('b',40000));
|
||||||
|
SET DEBUG_SYNC='before_row_upd_extern SIGNAL have_latch WAIT_FOR go1';
|
||||||
|
BEGIN;
|
||||||
|
# This will not block, because it will not store new BLOBs.
|
||||||
|
UPDATE t1 SET a=a+2;
|
||||||
|
ROLLBACK;
|
||||||
|
BEGIN;
|
||||||
|
--send
|
||||||
|
UPDATE t1 SET b=CONCAT(b,'foo');
|
||||||
|
|
||||||
|
connect (con1,localhost,root,,);
|
||||||
|
SET DEBUG_SYNC='now WAIT_FOR have_latch';
|
||||||
|
|
||||||
|
# this one should block due to the clustered index tree and leaf page latches
|
||||||
|
--send
|
||||||
|
SELECT a, RIGHT(b,20) FROM t1;
|
||||||
|
|
||||||
|
connect (con2,localhost,root,,);
|
||||||
|
|
||||||
|
# Check that the above SELECT is blocked
|
||||||
|
let $wait_condition=
|
||||||
|
select count(*) = 1 from information_schema.processlist
|
||||||
|
where state = 'Sending data' and
|
||||||
|
info = 'SELECT a, RIGHT(b,20) FROM t1';
|
||||||
|
--source include/wait_condition.inc
|
||||||
|
|
||||||
|
SET DEBUG_SYNC='now SIGNAL go1';
|
||||||
|
|
||||||
|
connection con1;
|
||||||
|
reap;
|
||||||
|
connection default;
|
||||||
|
reap;
|
||||||
|
SET DEBUG='+d,row_ins_extern_checkpoint';
|
||||||
|
SET DEBUG_SYNC='before_row_ins_extern_latch SIGNAL rec_not_blob WAIT_FOR crash';
|
||||||
|
ROLLBACK;
|
||||||
|
BEGIN;
|
||||||
|
--send
|
||||||
|
INSERT INTO t1 VALUES (3,REPEAT('c',50000));
|
||||||
|
|
||||||
|
connection con1;
|
||||||
|
SET DEBUG_SYNC='now WAIT_FOR rec_not_blob';
|
||||||
|
SET SESSION TRANSACTION ISOLATION LEVEL READ UNCOMMITTED;
|
||||||
|
SELECT @@tx_isolation;
|
||||||
|
|
||||||
|
# this one should see (3,NULL_BLOB)
|
||||||
|
SELECT a, RIGHT(b,20) FROM t1;
|
||||||
|
SELECT a FROM t1;
|
||||||
|
|
||||||
|
# Request a crash, and restart the server.
|
||||||
|
SET DEBUG='+d,crash_commit_before';
|
||||||
|
--exec echo "restart" > $MYSQLTEST_VARDIR/tmp/mysqld.1.expect
|
||||||
|
--error 2013
|
||||||
|
INSERT INTO t2 VALUES (42);
|
||||||
|
|
||||||
|
disconnect con1;
|
||||||
|
disconnect con2;
|
||||||
|
connection default;
|
||||||
|
# This connection should notice the crash as well.
|
||||||
|
--error 2013
|
||||||
|
reap;
|
||||||
|
|
||||||
|
# Write file to make mysql-test-run.pl restart the server
|
||||||
|
--enable_reconnect
|
||||||
|
--source include/wait_until_connected_again.inc
|
||||||
|
--disable_reconnect
|
||||||
|
|
||||||
|
CHECK TABLE t1;
|
||||||
|
|
||||||
|
INSERT INTO t3 VALUES
|
||||||
|
(1,REPEAT('d',7000),REPEAT('e',100)),
|
||||||
|
(2,REPEAT('g',7000),REPEAT('h',100));
|
||||||
|
SET DEBUG_SYNC='before_row_upd_extern SIGNAL have_latch WAIT_FOR go';
|
||||||
|
# This should move column b off-page.
|
||||||
|
--send
|
||||||
|
UPDATE t3 SET c=REPEAT('f',3000) WHERE a=1;
|
||||||
|
|
||||||
|
connect (con1,localhost,root,,);
|
||||||
|
SET DEBUG_SYNC='now WAIT_FOR have_latch';
|
||||||
|
SET SESSION TRANSACTION ISOLATION LEVEL READ UNCOMMITTED;
|
||||||
|
SELECT @@tx_isolation;
|
||||||
|
|
||||||
|
# this one should block
|
||||||
|
-- send
|
||||||
|
SELECT a, RIGHT(b,20), RIGHT(c,20) FROM t3;
|
||||||
|
|
||||||
|
connect (con2,localhost,root,,);
|
||||||
|
|
||||||
|
# Check that the above SELECT is blocked
|
||||||
|
let $wait_condition=
|
||||||
|
select count(*) = 1 from information_schema.processlist
|
||||||
|
where state = 'Sending data' and
|
||||||
|
info = 'SELECT a, RIGHT(b,20), RIGHT(c,20) FROM t3';
|
||||||
|
--source include/wait_condition.inc
|
||||||
|
|
||||||
|
SET DEBUG_SYNC='now SIGNAL go';
|
||||||
|
|
||||||
|
connection con1;
|
||||||
|
reap;
|
||||||
|
disconnect con1;
|
||||||
|
|
||||||
|
connection default;
|
||||||
|
reap;
|
||||||
|
|
||||||
|
CHECK TABLE t1,t2,t3;
|
||||||
|
|
||||||
|
connection con2;
|
||||||
|
BEGIN;
|
||||||
|
INSERT INTO t2 VALUES (347);
|
||||||
|
connection default;
|
||||||
|
|
||||||
|
# The row_upd_extern_checkpoint was removed in Bug#13721257,
|
||||||
|
# because the mini-transaction of the B-tree modification would
|
||||||
|
# remain open while we are writing the off-page columns and are
|
||||||
|
# stuck in the DEBUG_SYNC. A checkpoint involves a flush, which
|
||||||
|
# would wait for the buffer-fix to cease.
|
||||||
|
SET DEBUG='+d,row_upd_extern_checkpoint';
|
||||||
|
SET DEBUG_SYNC='before_row_upd_extern SIGNAL have_latch WAIT_FOR crash';
|
||||||
|
# This should move column b off-page.
|
||||||
|
--send
|
||||||
|
UPDATE t3 SET c=REPEAT('i',3000) WHERE a=2;
|
||||||
|
|
||||||
|
connection con2;
|
||||||
|
SET DEBUG_SYNC='now WAIT_FOR have_latch';
|
||||||
|
|
||||||
|
# Check that the above UPDATE is blocked
|
||||||
|
SELECT info FROM information_schema.processlist
|
||||||
|
WHERE state = 'debug sync point: before_row_upd_extern';
|
||||||
|
|
||||||
|
# Request a crash, and restart the server.
|
||||||
|
SET DEBUG='+d,crash_commit_before';
|
||||||
|
--exec echo "restart" > $MYSQLTEST_VARDIR/tmp/mysqld.1.expect
|
||||||
|
--error 2013
|
||||||
|
COMMIT;
|
||||||
|
|
||||||
|
disconnect con2;
|
||||||
|
connection default;
|
||||||
|
# This connection should notice the crash as well.
|
||||||
|
--error 2013
|
||||||
|
reap;
|
||||||
|
|
||||||
|
# Write file to make mysql-test-run.pl restart the server
|
||||||
|
--enable_reconnect
|
||||||
|
--source include/wait_until_connected_again.inc
|
||||||
|
--disable_reconnect
|
||||||
|
|
||||||
|
CHECK TABLE t1,t2,t3;
|
||||||
|
SELECT a, RIGHT(b,20), RIGHT(c,20) FROM t3;
|
||||||
|
SELECT a FROM t3;
|
||||||
|
|
||||||
|
connect (con2,localhost,root,,);
|
||||||
|
BEGIN;
|
||||||
|
INSERT INTO t2 VALUES (33101);
|
||||||
|
connection default;
|
||||||
|
|
||||||
|
# The row_upd_extern_checkpoint was removed in Bug#13721257,
|
||||||
|
# because the mini-transaction of the B-tree modification would
|
||||||
|
# remain open while we are writing the off-page columns and are
|
||||||
|
# stuck in the DEBUG_SYNC. A checkpoint involves a flush, which
|
||||||
|
# would wait for the buffer-fix to cease.
|
||||||
|
SET DEBUG='+d,row_upd_extern_checkpoint';
|
||||||
|
SET DEBUG_SYNC='after_row_upd_extern SIGNAL have_latch WAIT_FOR crash';
|
||||||
|
# This should move column b off-page.
|
||||||
|
--send
|
||||||
|
UPDATE t3 SET c=REPEAT('j',3000) WHERE a=2;
|
||||||
|
|
||||||
|
connection con2;
|
||||||
|
SET DEBUG_SYNC='now WAIT_FOR have_latch';
|
||||||
|
|
||||||
|
# Check that the above UPDATE is blocked
|
||||||
|
SELECT info FROM information_schema.processlist
|
||||||
|
WHERE state = 'debug sync point: after_row_upd_extern';
|
||||||
|
|
||||||
|
# Request a crash, and restart the server.
|
||||||
|
SET DEBUG='+d,crash_commit_before';
|
||||||
|
--exec echo "restart" > $MYSQLTEST_VARDIR/tmp/mysqld.1.expect
|
||||||
|
--error 2013
|
||||||
|
COMMIT;
|
||||||
|
|
||||||
|
disconnect con2;
|
||||||
|
connection default;
|
||||||
|
# This connection should notice the crash as well.
|
||||||
|
--error 2013
|
||||||
|
reap;
|
||||||
|
|
||||||
|
# Write file to make mysql-test-run.pl restart the server
|
||||||
|
--enable_reconnect
|
||||||
|
--source include/wait_until_connected_again.inc
|
||||||
|
--disable_reconnect
|
||||||
|
|
||||||
|
CHECK TABLE t1,t2,t3;
|
||||||
|
SELECT a, RIGHT(b,20), RIGHT(c,20) FROM t3;
|
||||||
|
SELECT a FROM t3;
|
||||||
|
|
||||||
|
SELECT * FROM t2;
|
||||||
|
|
||||||
|
DROP TABLE t1,t2,t3;
|
@ -11,8 +11,8 @@ ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
|||||||
FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
|
FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
|
||||||
|
|
||||||
You should have received a copy of the GNU General Public License along with
|
You should have received a copy of the GNU General Public License along with
|
||||||
this program; if not, write to the Free Software Foundation, Inc., 59 Temple
|
this program; if not, write to the Free Software Foundation, Inc.,
|
||||||
Place, Suite 330, Boston, MA 02111-1307 USA
|
51 Franklin Street, Suite 500, Boston, MA 02110-1335 USA
|
||||||
|
|
||||||
*****************************************************************************/
|
*****************************************************************************/
|
||||||
|
|
||||||
@ -927,28 +927,31 @@ btr_page_alloc_for_ibuf(
|
|||||||
/**************************************************************//**
|
/**************************************************************//**
|
||||||
Allocates a new file page to be used in an index tree. NOTE: we assume
|
Allocates a new file page to be used in an index tree. NOTE: we assume
|
||||||
that the caller has made the reservation for free extents!
|
that the caller has made the reservation for free extents!
|
||||||
@return new allocated block, x-latched; NULL if out of space */
|
@retval NULL if no page could be allocated
|
||||||
UNIV_INTERN
|
@retval block, rw_lock_x_lock_count(&block->lock) == 1 if allocation succeeded
|
||||||
|
(init_mtr == mtr, or the page was not previously freed in mtr)
|
||||||
|
@retval block (not allocated or initialized) otherwise */
|
||||||
|
static __attribute__((nonnull, warn_unused_result))
|
||||||
buf_block_t*
|
buf_block_t*
|
||||||
btr_page_alloc(
|
btr_page_alloc_low(
|
||||||
/*===========*/
|
/*===============*/
|
||||||
dict_index_t* index, /*!< in: index */
|
dict_index_t* index, /*!< in: index */
|
||||||
ulint hint_page_no, /*!< in: hint of a good page */
|
ulint hint_page_no, /*!< in: hint of a good page */
|
||||||
byte file_direction, /*!< in: direction where a possible
|
byte file_direction, /*!< in: direction where a possible
|
||||||
page split is made */
|
page split is made */
|
||||||
ulint level, /*!< in: level where the page is placed
|
ulint level, /*!< in: level where the page is placed
|
||||||
in the tree */
|
in the tree */
|
||||||
mtr_t* mtr) /*!< in: mtr */
|
mtr_t* mtr, /*!< in/out: mini-transaction
|
||||||
|
for the allocation */
|
||||||
|
mtr_t* init_mtr) /*!< in/out: mtr or another
|
||||||
|
mini-transaction in which the
|
||||||
|
page should be initialized.
|
||||||
|
If init_mtr!=mtr, but the page
|
||||||
|
is already X-latched in mtr, do
|
||||||
|
not initialize the page. */
|
||||||
{
|
{
|
||||||
fseg_header_t* seg_header;
|
fseg_header_t* seg_header;
|
||||||
page_t* root;
|
page_t* root;
|
||||||
buf_block_t* new_block;
|
|
||||||
ulint new_page_no;
|
|
||||||
|
|
||||||
if (dict_index_is_ibuf(index)) {
|
|
||||||
|
|
||||||
return(btr_page_alloc_for_ibuf(index, mtr));
|
|
||||||
}
|
|
||||||
|
|
||||||
root = btr_root_get(index, mtr);
|
root = btr_root_get(index, mtr);
|
||||||
|
|
||||||
@ -962,17 +965,47 @@ btr_page_alloc(
|
|||||||
reservation for free extents, and thus we know that a page can
|
reservation for free extents, and thus we know that a page can
|
||||||
be allocated: */
|
be allocated: */
|
||||||
|
|
||||||
new_page_no = fseg_alloc_free_page_general(seg_header, hint_page_no,
|
return(fseg_alloc_free_page_general(
|
||||||
file_direction, TRUE, mtr);
|
seg_header, hint_page_no, file_direction,
|
||||||
if (new_page_no == FIL_NULL) {
|
TRUE, mtr, init_mtr));
|
||||||
|
}
|
||||||
|
|
||||||
return(NULL);
|
/**************************************************************//**
|
||||||
|
Allocates a new file page to be used in an index tree. NOTE: we assume
|
||||||
|
that the caller has made the reservation for free extents!
|
||||||
|
@retval NULL if no page could be allocated
|
||||||
|
@retval block, rw_lock_x_lock_count(&block->lock) == 1 if allocation succeeded
|
||||||
|
(init_mtr == mtr, or the page was not previously freed in mtr)
|
||||||
|
@retval block (not allocated or initialized) otherwise */
|
||||||
|
UNIV_INTERN
|
||||||
|
buf_block_t*
|
||||||
|
btr_page_alloc(
|
||||||
|
/*===========*/
|
||||||
|
dict_index_t* index, /*!< in: index */
|
||||||
|
ulint hint_page_no, /*!< in: hint of a good page */
|
||||||
|
byte file_direction, /*!< in: direction where a possible
|
||||||
|
page split is made */
|
||||||
|
ulint level, /*!< in: level where the page is placed
|
||||||
|
in the tree */
|
||||||
|
mtr_t* mtr, /*!< in/out: mini-transaction
|
||||||
|
for the allocation */
|
||||||
|
mtr_t* init_mtr) /*!< in/out: mini-transaction
|
||||||
|
for x-latching and initializing
|
||||||
|
the page */
|
||||||
|
{
|
||||||
|
buf_block_t* new_block;
|
||||||
|
|
||||||
|
if (dict_index_is_ibuf(index)) {
|
||||||
|
|
||||||
|
return(btr_page_alloc_for_ibuf(index, mtr));
|
||||||
}
|
}
|
||||||
|
|
||||||
new_block = buf_page_get(dict_index_get_space(index),
|
new_block = btr_page_alloc_low(
|
||||||
dict_table_zip_size(index->table),
|
index, hint_page_no, file_direction, level, mtr, init_mtr);
|
||||||
new_page_no, RW_X_LATCH, mtr);
|
|
||||||
buf_block_dbg_add_level(new_block, SYNC_TREE_NODE_NEW);
|
if (new_block) {
|
||||||
|
buf_block_dbg_add_level(new_block, SYNC_TREE_NODE_NEW);
|
||||||
|
}
|
||||||
|
|
||||||
return(new_block);
|
return(new_block);
|
||||||
}
|
}
|
||||||
@ -1099,10 +1132,10 @@ btr_page_free(
|
|||||||
buf_block_t* block, /*!< in: block to be freed, x-latched */
|
buf_block_t* block, /*!< in: block to be freed, x-latched */
|
||||||
mtr_t* mtr) /*!< in: mtr */
|
mtr_t* mtr) /*!< in: mtr */
|
||||||
{
|
{
|
||||||
ulint level;
|
const page_t* page = buf_block_get_frame(block);
|
||||||
|
ulint level = btr_page_get_level(page, mtr);
|
||||||
level = btr_page_get_level(buf_block_get_frame(block), mtr);
|
|
||||||
|
|
||||||
|
ut_ad(fil_page_get_type(block->frame) == FIL_PAGE_INDEX);
|
||||||
btr_page_free_low(index, block, level, mtr);
|
btr_page_free_low(index, block, level, mtr);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1344,16 +1377,12 @@ btr_create(
|
|||||||
/* Allocate then the next page to the segment: it will be the
|
/* Allocate then the next page to the segment: it will be the
|
||||||
tree root page */
|
tree root page */
|
||||||
|
|
||||||
page_no = fseg_alloc_free_page(buf_block_get_frame(
|
block = fseg_alloc_free_page(
|
||||||
ibuf_hdr_block)
|
buf_block_get_frame(ibuf_hdr_block)
|
||||||
+ IBUF_HEADER
|
+ IBUF_HEADER + IBUF_TREE_SEG_HEADER,
|
||||||
+ IBUF_TREE_SEG_HEADER,
|
IBUF_TREE_ROOT_PAGE_NO,
|
||||||
IBUF_TREE_ROOT_PAGE_NO,
|
FSP_UP, mtr);
|
||||||
FSP_UP, mtr);
|
ut_ad(buf_block_get_page_no(block) == IBUF_TREE_ROOT_PAGE_NO);
|
||||||
ut_ad(page_no == IBUF_TREE_ROOT_PAGE_NO);
|
|
||||||
|
|
||||||
block = buf_page_get(space, zip_size, page_no,
|
|
||||||
RW_X_LATCH, mtr);
|
|
||||||
} else {
|
} else {
|
||||||
#ifdef UNIV_BLOB_DEBUG
|
#ifdef UNIV_BLOB_DEBUG
|
||||||
if ((type & DICT_CLUSTERED) && !index->blobs) {
|
if ((type & DICT_CLUSTERED) && !index->blobs) {
|
||||||
@ -1833,7 +1862,7 @@ btr_root_raise_and_insert(
|
|||||||
|
|
||||||
level = btr_page_get_level(root, mtr);
|
level = btr_page_get_level(root, mtr);
|
||||||
|
|
||||||
new_block = btr_page_alloc(index, 0, FSP_NO_DIR, level, mtr);
|
new_block = btr_page_alloc(index, 0, FSP_NO_DIR, level, mtr, mtr);
|
||||||
new_page = buf_block_get_frame(new_block);
|
new_page = buf_block_get_frame(new_block);
|
||||||
new_page_zip = buf_block_get_page_zip(new_block);
|
new_page_zip = buf_block_get_page_zip(new_block);
|
||||||
ut_a(!new_page_zip == !root_page_zip);
|
ut_a(!new_page_zip == !root_page_zip);
|
||||||
@ -2569,7 +2598,7 @@ func_start:
|
|||||||
|
|
||||||
/* 2. Allocate a new page to the index */
|
/* 2. Allocate a new page to the index */
|
||||||
new_block = btr_page_alloc(cursor->index, hint_page_no, direction,
|
new_block = btr_page_alloc(cursor->index, hint_page_no, direction,
|
||||||
btr_page_get_level(page, mtr), mtr);
|
btr_page_get_level(page, mtr), mtr, mtr);
|
||||||
new_page = buf_block_get_frame(new_block);
|
new_page = buf_block_get_frame(new_block);
|
||||||
new_page_zip = buf_block_get_page_zip(new_block);
|
new_page_zip = buf_block_get_page_zip(new_block);
|
||||||
btr_page_create(new_block, new_page_zip, cursor->index,
|
btr_page_create(new_block, new_page_zip, cursor->index,
|
||||||
@ -3019,15 +3048,16 @@ btr_node_ptr_delete(
|
|||||||
ut_a(err == DB_SUCCESS);
|
ut_a(err == DB_SUCCESS);
|
||||||
|
|
||||||
if (!compressed) {
|
if (!compressed) {
|
||||||
btr_cur_compress_if_useful(&cursor, mtr);
|
btr_cur_compress_if_useful(&cursor, FALSE, mtr);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/*************************************************************//**
|
/*************************************************************//**
|
||||||
If page is the only on its level, this function moves its records to the
|
If page is the only on its level, this function moves its records to the
|
||||||
father page, thus reducing the tree height. */
|
father page, thus reducing the tree height.
|
||||||
|
@return father block */
|
||||||
static
|
static
|
||||||
void
|
buf_block_t*
|
||||||
btr_lift_page_up(
|
btr_lift_page_up(
|
||||||
/*=============*/
|
/*=============*/
|
||||||
dict_index_t* index, /*!< in: index tree */
|
dict_index_t* index, /*!< in: index tree */
|
||||||
@ -3144,6 +3174,8 @@ btr_lift_page_up(
|
|||||||
}
|
}
|
||||||
ut_ad(page_validate(father_page, index));
|
ut_ad(page_validate(father_page, index));
|
||||||
ut_ad(btr_check_node_ptr(index, father_block, mtr));
|
ut_ad(btr_check_node_ptr(index, father_block, mtr));
|
||||||
|
|
||||||
|
return(father_block);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*************************************************************//**
|
/*************************************************************//**
|
||||||
@ -3160,11 +3192,13 @@ UNIV_INTERN
|
|||||||
ibool
|
ibool
|
||||||
btr_compress(
|
btr_compress(
|
||||||
/*=========*/
|
/*=========*/
|
||||||
btr_cur_t* cursor, /*!< in: cursor on the page to merge or lift;
|
btr_cur_t* cursor, /*!< in/out: cursor on the page to merge
|
||||||
the page must not be empty: in record delete
|
or lift; the page must not be empty:
|
||||||
use btr_discard_page if the page would become
|
when deleting records, use btr_discard_page()
|
||||||
empty */
|
if the page would become empty */
|
||||||
mtr_t* mtr) /*!< in: mtr */
|
ibool adjust, /*!< in: TRUE if should adjust the
|
||||||
|
cursor position even if compression occurs */
|
||||||
|
mtr_t* mtr) /*!< in/out: mini-transaction */
|
||||||
{
|
{
|
||||||
dict_index_t* index;
|
dict_index_t* index;
|
||||||
ulint space;
|
ulint space;
|
||||||
@ -3182,6 +3216,7 @@ btr_compress(
|
|||||||
ulint* offsets;
|
ulint* offsets;
|
||||||
ulint data_size;
|
ulint data_size;
|
||||||
ulint n_recs;
|
ulint n_recs;
|
||||||
|
ulint nth_rec = 0; /* remove bogus warning */
|
||||||
ulint max_ins_size;
|
ulint max_ins_size;
|
||||||
ulint max_ins_size_reorg;
|
ulint max_ins_size_reorg;
|
||||||
|
|
||||||
@ -3209,6 +3244,10 @@ btr_compress(
|
|||||||
offsets = btr_page_get_father_block(NULL, heap, index, block, mtr,
|
offsets = btr_page_get_father_block(NULL, heap, index, block, mtr,
|
||||||
&father_cursor);
|
&father_cursor);
|
||||||
|
|
||||||
|
if (adjust) {
|
||||||
|
nth_rec = page_rec_get_n_recs_before(btr_cur_get_rec(cursor));
|
||||||
|
}
|
||||||
|
|
||||||
/* Decide the page to which we try to merge and which will inherit
|
/* Decide the page to which we try to merge and which will inherit
|
||||||
the locks */
|
the locks */
|
||||||
|
|
||||||
@ -3235,9 +3274,9 @@ btr_compress(
|
|||||||
} else {
|
} else {
|
||||||
/* The page is the only one on the level, lift the records
|
/* The page is the only one on the level, lift the records
|
||||||
to the father */
|
to the father */
|
||||||
btr_lift_page_up(index, block, mtr);
|
|
||||||
mem_heap_free(heap);
|
merge_block = btr_lift_page_up(index, block, mtr);
|
||||||
return(TRUE);
|
goto func_exit;
|
||||||
}
|
}
|
||||||
|
|
||||||
n_recs = page_get_n_recs(page);
|
n_recs = page_get_n_recs(page);
|
||||||
@ -3319,6 +3358,10 @@ err_exit:
|
|||||||
|
|
||||||
btr_node_ptr_delete(index, block, mtr);
|
btr_node_ptr_delete(index, block, mtr);
|
||||||
lock_update_merge_left(merge_block, orig_pred, block);
|
lock_update_merge_left(merge_block, orig_pred, block);
|
||||||
|
|
||||||
|
if (adjust) {
|
||||||
|
nth_rec += page_rec_get_n_recs_before(orig_pred);
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
rec_t* orig_succ;
|
rec_t* orig_succ;
|
||||||
#ifdef UNIV_BTR_DEBUG
|
#ifdef UNIV_BTR_DEBUG
|
||||||
@ -3383,7 +3426,6 @@ err_exit:
|
|||||||
}
|
}
|
||||||
|
|
||||||
btr_blob_dbg_remove(page, index, "btr_compress");
|
btr_blob_dbg_remove(page, index, "btr_compress");
|
||||||
mem_heap_free(heap);
|
|
||||||
|
|
||||||
if (!dict_index_is_clust(index) && page_is_leaf(merge_page)) {
|
if (!dict_index_is_clust(index) && page_is_leaf(merge_page)) {
|
||||||
/* Update the free bits of the B-tree page in the
|
/* Update the free bits of the B-tree page in the
|
||||||
@ -3435,6 +3477,16 @@ err_exit:
|
|||||||
btr_page_free(index, block, mtr);
|
btr_page_free(index, block, mtr);
|
||||||
|
|
||||||
ut_ad(btr_check_node_ptr(index, merge_block, mtr));
|
ut_ad(btr_check_node_ptr(index, merge_block, mtr));
|
||||||
|
func_exit:
|
||||||
|
mem_heap_free(heap);
|
||||||
|
|
||||||
|
if (adjust) {
|
||||||
|
btr_cur_position(
|
||||||
|
index,
|
||||||
|
page_rec_get_nth(merge_block->frame, nth_rec),
|
||||||
|
merge_block, cursor);
|
||||||
|
}
|
||||||
|
|
||||||
return(TRUE);
|
return(TRUE);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -18,8 +18,8 @@ ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
|||||||
FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
|
FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
|
||||||
|
|
||||||
You should have received a copy of the GNU General Public License along with
|
You should have received a copy of the GNU General Public License along with
|
||||||
this program; if not, write to the Free Software Foundation, Inc., 59 Temple
|
this program; if not, write to the Free Software Foundation, Inc.,
|
||||||
Place, Suite 330, Boston, MA 02111-1307 USA
|
51 Franklin Street, Suite 500, Boston, MA 02110-1335 USA
|
||||||
|
|
||||||
*****************************************************************************/
|
*****************************************************************************/
|
||||||
|
|
||||||
@ -1860,7 +1860,7 @@ btr_cur_update_in_place(
|
|||||||
page_zip = buf_block_get_page_zip(block);
|
page_zip = buf_block_get_page_zip(block);
|
||||||
|
|
||||||
/* Check that enough space is available on the compressed page. */
|
/* Check that enough space is available on the compressed page. */
|
||||||
if (UNIV_LIKELY_NULL(page_zip)
|
if (page_zip
|
||||||
&& !btr_cur_update_alloc_zip(page_zip, block, index,
|
&& !btr_cur_update_alloc_zip(page_zip, block, index,
|
||||||
rec_offs_size(offsets), FALSE, mtr)) {
|
rec_offs_size(offsets), FALSE, mtr)) {
|
||||||
return(DB_ZIP_OVERFLOW);
|
return(DB_ZIP_OVERFLOW);
|
||||||
@ -2051,7 +2051,7 @@ any_extern:
|
|||||||
ut_a(!page_zip || page_zip_validate(page_zip, page));
|
ut_a(!page_zip || page_zip_validate(page_zip, page));
|
||||||
#endif /* UNIV_ZIP_DEBUG */
|
#endif /* UNIV_ZIP_DEBUG */
|
||||||
|
|
||||||
if (UNIV_LIKELY_NULL(page_zip)
|
if (page_zip
|
||||||
&& !btr_cur_update_alloc_zip(page_zip, block, index,
|
&& !btr_cur_update_alloc_zip(page_zip, block, index,
|
||||||
new_rec_size, TRUE, mtr)) {
|
new_rec_size, TRUE, mtr)) {
|
||||||
err = DB_ZIP_OVERFLOW;
|
err = DB_ZIP_OVERFLOW;
|
||||||
@ -2209,7 +2209,9 @@ btr_cur_pessimistic_update(
|
|||||||
/*=======================*/
|
/*=======================*/
|
||||||
ulint flags, /*!< in: undo logging, locking, and rollback
|
ulint flags, /*!< in: undo logging, locking, and rollback
|
||||||
flags */
|
flags */
|
||||||
btr_cur_t* cursor, /*!< in: cursor on the record to update */
|
btr_cur_t* cursor, /*!< in/out: cursor on the record to update;
|
||||||
|
cursor may become invalid if *big_rec == NULL
|
||||||
|
|| !(flags & BTR_KEEP_POS_FLAG) */
|
||||||
mem_heap_t** heap, /*!< in/out: pointer to memory heap, or NULL */
|
mem_heap_t** heap, /*!< in/out: pointer to memory heap, or NULL */
|
||||||
big_rec_t** big_rec,/*!< out: big rec vector whose fields have to
|
big_rec_t** big_rec,/*!< out: big rec vector whose fields have to
|
||||||
be stored externally by the caller, or NULL */
|
be stored externally by the caller, or NULL */
|
||||||
@ -2348,10 +2350,10 @@ btr_cur_pessimistic_update(
|
|||||||
record to be inserted: we have to remember which fields were such */
|
record to be inserted: we have to remember which fields were such */
|
||||||
|
|
||||||
ut_ad(!page_is_comp(page) || !rec_get_node_ptr_flag(rec));
|
ut_ad(!page_is_comp(page) || !rec_get_node_ptr_flag(rec));
|
||||||
offsets = rec_get_offsets(rec, index, offsets, ULINT_UNDEFINED, heap);
|
ut_ad(rec_offs_validate(rec, index, offsets));
|
||||||
n_ext += btr_push_update_extern_fields(new_entry, update, *heap);
|
n_ext += btr_push_update_extern_fields(new_entry, update, *heap);
|
||||||
|
|
||||||
if (UNIV_LIKELY_NULL(page_zip)) {
|
if (page_zip) {
|
||||||
ut_ad(page_is_comp(page));
|
ut_ad(page_is_comp(page));
|
||||||
if (page_zip_rec_needs_ext(
|
if (page_zip_rec_needs_ext(
|
||||||
rec_get_converted_size(index, new_entry, n_ext),
|
rec_get_converted_size(index, new_entry, n_ext),
|
||||||
@ -2371,6 +2373,10 @@ make_external:
|
|||||||
err = DB_TOO_BIG_RECORD;
|
err = DB_TOO_BIG_RECORD;
|
||||||
goto return_after_reservations;
|
goto return_after_reservations;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ut_ad(page_is_leaf(page));
|
||||||
|
ut_ad(dict_index_is_clust(index));
|
||||||
|
ut_ad(flags & BTR_KEEP_POS_FLAG);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Store state of explicit locks on rec on the page infimum record,
|
/* Store state of explicit locks on rec on the page infimum record,
|
||||||
@ -2398,6 +2404,8 @@ make_external:
|
|||||||
rec = btr_cur_insert_if_possible(cursor, new_entry, n_ext, mtr);
|
rec = btr_cur_insert_if_possible(cursor, new_entry, n_ext, mtr);
|
||||||
|
|
||||||
if (rec) {
|
if (rec) {
|
||||||
|
page_cursor->rec = rec;
|
||||||
|
|
||||||
lock_rec_restore_from_page_infimum(btr_cur_get_block(cursor),
|
lock_rec_restore_from_page_infimum(btr_cur_get_block(cursor),
|
||||||
rec, block);
|
rec, block);
|
||||||
|
|
||||||
@ -2411,7 +2419,10 @@ make_external:
|
|||||||
rec, index, offsets, mtr);
|
rec, index, offsets, mtr);
|
||||||
}
|
}
|
||||||
|
|
||||||
btr_cur_compress_if_useful(cursor, mtr);
|
btr_cur_compress_if_useful(
|
||||||
|
cursor,
|
||||||
|
big_rec_vec != NULL && (flags & BTR_KEEP_POS_FLAG),
|
||||||
|
mtr);
|
||||||
|
|
||||||
if (page_zip && !dict_index_is_clust(index)
|
if (page_zip && !dict_index_is_clust(index)
|
||||||
&& page_is_leaf(page)) {
|
&& page_is_leaf(page)) {
|
||||||
@ -2431,6 +2442,21 @@ make_external:
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (big_rec_vec) {
|
||||||
|
ut_ad(page_is_leaf(page));
|
||||||
|
ut_ad(dict_index_is_clust(index));
|
||||||
|
ut_ad(flags & BTR_KEEP_POS_FLAG);
|
||||||
|
|
||||||
|
/* btr_page_split_and_insert() in
|
||||||
|
btr_cur_pessimistic_insert() invokes
|
||||||
|
mtr_memo_release(mtr, index->lock, MTR_MEMO_X_LOCK).
|
||||||
|
We must keep the index->lock when we created a
|
||||||
|
big_rec, so that row_upd_clust_rec() can store the
|
||||||
|
big_rec in the same mini-transaction. */
|
||||||
|
|
||||||
|
mtr_x_lock(dict_index_get_lock(index), mtr);
|
||||||
|
}
|
||||||
|
|
||||||
/* Was the record to be updated positioned as the first user
|
/* Was the record to be updated positioned as the first user
|
||||||
record on its page? */
|
record on its page? */
|
||||||
was_first = page_cur_is_before_first(page_cursor);
|
was_first = page_cur_is_before_first(page_cursor);
|
||||||
@ -2446,6 +2472,7 @@ make_external:
|
|||||||
ut_a(rec);
|
ut_a(rec);
|
||||||
ut_a(err == DB_SUCCESS);
|
ut_a(err == DB_SUCCESS);
|
||||||
ut_a(dummy_big_rec == NULL);
|
ut_a(dummy_big_rec == NULL);
|
||||||
|
page_cursor->rec = rec;
|
||||||
|
|
||||||
if (dict_index_is_sec_or_ibuf(index)) {
|
if (dict_index_is_sec_or_ibuf(index)) {
|
||||||
/* Update PAGE_MAX_TRX_ID in the index page header.
|
/* Update PAGE_MAX_TRX_ID in the index page header.
|
||||||
@ -2880,10 +2907,12 @@ UNIV_INTERN
|
|||||||
ibool
|
ibool
|
||||||
btr_cur_compress_if_useful(
|
btr_cur_compress_if_useful(
|
||||||
/*=======================*/
|
/*=======================*/
|
||||||
btr_cur_t* cursor, /*!< in: cursor on the page to compress;
|
btr_cur_t* cursor, /*!< in/out: cursor on the page to compress;
|
||||||
cursor does not stay valid if compression
|
cursor does not stay valid if !adjust and
|
||||||
occurs */
|
compression occurs */
|
||||||
mtr_t* mtr) /*!< in: mtr */
|
ibool adjust, /*!< in: TRUE if should adjust the
|
||||||
|
cursor position even if compression occurs */
|
||||||
|
mtr_t* mtr) /*!< in/out: mini-transaction */
|
||||||
{
|
{
|
||||||
ut_ad(mtr_memo_contains(mtr,
|
ut_ad(mtr_memo_contains(mtr,
|
||||||
dict_index_get_lock(btr_cur_get_index(cursor)),
|
dict_index_get_lock(btr_cur_get_index(cursor)),
|
||||||
@ -2892,7 +2921,7 @@ btr_cur_compress_if_useful(
|
|||||||
MTR_MEMO_PAGE_X_FIX));
|
MTR_MEMO_PAGE_X_FIX));
|
||||||
|
|
||||||
return(btr_cur_compress_recommendation(cursor, mtr)
|
return(btr_cur_compress_recommendation(cursor, mtr)
|
||||||
&& btr_compress(cursor, mtr));
|
&& btr_compress(cursor, adjust, mtr));
|
||||||
}
|
}
|
||||||
|
|
||||||
/*******************************************************//**
|
/*******************************************************//**
|
||||||
@ -3134,7 +3163,7 @@ return_after_reservations:
|
|||||||
mem_heap_free(heap);
|
mem_heap_free(heap);
|
||||||
|
|
||||||
if (ret == FALSE) {
|
if (ret == FALSE) {
|
||||||
ret = btr_cur_compress_if_useful(cursor, mtr);
|
ret = btr_cur_compress_if_useful(cursor, FALSE, mtr);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (n_extents > 0) {
|
if (n_extents > 0) {
|
||||||
@ -3870,10 +3899,10 @@ btr_cur_set_ownership_of_extern_field(
|
|||||||
byte_val = byte_val | BTR_EXTERN_OWNER_FLAG;
|
byte_val = byte_val | BTR_EXTERN_OWNER_FLAG;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (UNIV_LIKELY_NULL(page_zip)) {
|
if (page_zip) {
|
||||||
mach_write_to_1(data + local_len + BTR_EXTERN_LEN, byte_val);
|
mach_write_to_1(data + local_len + BTR_EXTERN_LEN, byte_val);
|
||||||
page_zip_write_blob_ptr(page_zip, rec, index, offsets, i, mtr);
|
page_zip_write_blob_ptr(page_zip, rec, index, offsets, i, mtr);
|
||||||
} else if (UNIV_LIKELY(mtr != NULL)) {
|
} else if (mtr != NULL) {
|
||||||
|
|
||||||
mlog_write_ulint(data + local_len + BTR_EXTERN_LEN, byte_val,
|
mlog_write_ulint(data + local_len + BTR_EXTERN_LEN, byte_val,
|
||||||
MLOG_1BYTE, mtr);
|
MLOG_1BYTE, mtr);
|
||||||
@ -4106,9 +4135,9 @@ The fields are stored on pages allocated from leaf node
|
|||||||
file segment of the index tree.
|
file segment of the index tree.
|
||||||
@return DB_SUCCESS or DB_OUT_OF_FILE_SPACE */
|
@return DB_SUCCESS or DB_OUT_OF_FILE_SPACE */
|
||||||
UNIV_INTERN
|
UNIV_INTERN
|
||||||
ulint
|
enum db_err
|
||||||
btr_store_big_rec_extern_fields_func(
|
btr_store_big_rec_extern_fields(
|
||||||
/*=================================*/
|
/*============================*/
|
||||||
dict_index_t* index, /*!< in: index of rec; the index tree
|
dict_index_t* index, /*!< in: index of rec; the index tree
|
||||||
MUST be X-latched */
|
MUST be X-latched */
|
||||||
buf_block_t* rec_block, /*!< in/out: block containing rec */
|
buf_block_t* rec_block, /*!< in/out: block containing rec */
|
||||||
@ -4117,38 +4146,37 @@ btr_store_big_rec_extern_fields_func(
|
|||||||
the "external storage" flags in offsets
|
the "external storage" flags in offsets
|
||||||
will not correspond to rec when
|
will not correspond to rec when
|
||||||
this function returns */
|
this function returns */
|
||||||
#ifdef UNIV_DEBUG
|
const big_rec_t*big_rec_vec, /*!< in: vector containing fields
|
||||||
mtr_t* local_mtr, /*!< in: mtr containing the
|
|
||||||
latch to rec and to the tree */
|
|
||||||
#endif /* UNIV_DEBUG */
|
|
||||||
#if defined UNIV_DEBUG || defined UNIV_BLOB_LIGHT_DEBUG
|
|
||||||
ibool update_in_place,/*! in: TRUE if the record is updated
|
|
||||||
in place (not delete+insert) */
|
|
||||||
#endif /* UNIV_DEBUG || UNIV_BLOB_LIGHT_DEBUG */
|
|
||||||
const big_rec_t*big_rec_vec) /*!< in: vector containing fields
|
|
||||||
to be stored externally */
|
to be stored externally */
|
||||||
|
mtr_t* btr_mtr, /*!< in: mtr containing the
|
||||||
|
latches to the clustered index */
|
||||||
|
enum blob_op op) /*! in: operation code */
|
||||||
{
|
{
|
||||||
ulint rec_page_no;
|
ulint rec_page_no;
|
||||||
byte* field_ref;
|
byte* field_ref;
|
||||||
ulint extern_len;
|
ulint extern_len;
|
||||||
ulint store_len;
|
ulint store_len;
|
||||||
ulint page_no;
|
ulint page_no;
|
||||||
ulint space_id;
|
ulint space_id;
|
||||||
ulint zip_size;
|
ulint zip_size;
|
||||||
ulint prev_page_no;
|
ulint prev_page_no;
|
||||||
ulint hint_page_no;
|
ulint hint_page_no;
|
||||||
ulint i;
|
ulint i;
|
||||||
mtr_t mtr;
|
mtr_t mtr;
|
||||||
mem_heap_t* heap = NULL;
|
mtr_t* alloc_mtr;
|
||||||
|
mem_heap_t* heap = NULL;
|
||||||
page_zip_des_t* page_zip;
|
page_zip_des_t* page_zip;
|
||||||
z_stream c_stream;
|
z_stream c_stream;
|
||||||
|
buf_block_t** freed_pages = NULL;
|
||||||
|
ulint n_freed_pages = 0;
|
||||||
|
enum db_err error = DB_SUCCESS;
|
||||||
|
|
||||||
ut_ad(rec_offs_validate(rec, index, offsets));
|
ut_ad(rec_offs_validate(rec, index, offsets));
|
||||||
ut_ad(rec_offs_any_extern(offsets));
|
ut_ad(rec_offs_any_extern(offsets));
|
||||||
ut_ad(mtr_memo_contains(local_mtr, dict_index_get_lock(index),
|
ut_ad(btr_mtr);
|
||||||
|
ut_ad(mtr_memo_contains(btr_mtr, dict_index_get_lock(index),
|
||||||
MTR_MEMO_X_LOCK));
|
MTR_MEMO_X_LOCK));
|
||||||
ut_ad(mtr_memo_contains(local_mtr, rec_block, MTR_MEMO_PAGE_X_FIX));
|
ut_ad(mtr_memo_contains(btr_mtr, rec_block, MTR_MEMO_PAGE_X_FIX));
|
||||||
ut_ad(buf_block_get_frame(rec_block) == page_align(rec));
|
ut_ad(buf_block_get_frame(rec_block) == page_align(rec));
|
||||||
ut_a(dict_index_is_clust(index));
|
ut_a(dict_index_is_clust(index));
|
||||||
|
|
||||||
@ -4161,7 +4189,7 @@ btr_store_big_rec_extern_fields_func(
|
|||||||
rec_page_no = buf_block_get_page_no(rec_block);
|
rec_page_no = buf_block_get_page_no(rec_block);
|
||||||
ut_a(fil_page_get_type(page_align(rec)) == FIL_PAGE_INDEX);
|
ut_a(fil_page_get_type(page_align(rec)) == FIL_PAGE_INDEX);
|
||||||
|
|
||||||
if (UNIV_LIKELY_NULL(page_zip)) {
|
if (page_zip) {
|
||||||
int err;
|
int err;
|
||||||
|
|
||||||
/* Zlib deflate needs 128 kilobytes for the default
|
/* Zlib deflate needs 128 kilobytes for the default
|
||||||
@ -4177,6 +4205,42 @@ btr_store_big_rec_extern_fields_func(
|
|||||||
ut_a(err == Z_OK);
|
ut_a(err == Z_OK);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (btr_blob_op_is_update(op)) {
|
||||||
|
/* Avoid reusing pages that have been previously freed
|
||||||
|
in btr_mtr. */
|
||||||
|
if (btr_mtr->n_freed_pages) {
|
||||||
|
if (heap == NULL) {
|
||||||
|
heap = mem_heap_create(
|
||||||
|
btr_mtr->n_freed_pages
|
||||||
|
* sizeof *freed_pages);
|
||||||
|
}
|
||||||
|
|
||||||
|
freed_pages = mem_heap_alloc(
|
||||||
|
heap,
|
||||||
|
btr_mtr->n_freed_pages
|
||||||
|
* sizeof *freed_pages);
|
||||||
|
n_freed_pages = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Because btr_mtr will be committed after mtr, it is
|
||||||
|
possible that the tablespace has been extended when
|
||||||
|
the B-tree record was updated or inserted, or it will
|
||||||
|
be extended while allocating pages for big_rec.
|
||||||
|
|
||||||
|
TODO: In mtr (not btr_mtr), write a redo log record
|
||||||
|
about extending the tablespace to its current size,
|
||||||
|
and remember the current size. Whenever the tablespace
|
||||||
|
grows as pages are allocated, write further redo log
|
||||||
|
records to mtr. (Currently tablespace extension is not
|
||||||
|
covered by the redo log. If it were, the record would
|
||||||
|
only be written to btr_mtr, which is committed after
|
||||||
|
mtr.) */
|
||||||
|
alloc_mtr = btr_mtr;
|
||||||
|
} else {
|
||||||
|
/* Use the local mtr for allocations. */
|
||||||
|
alloc_mtr = &mtr;
|
||||||
|
}
|
||||||
|
|
||||||
#if defined UNIV_DEBUG || defined UNIV_BLOB_LIGHT_DEBUG
|
#if defined UNIV_DEBUG || defined UNIV_BLOB_LIGHT_DEBUG
|
||||||
/* All pointers to externally stored columns in the record
|
/* All pointers to externally stored columns in the record
|
||||||
must either be zero or they must be pointers to inherited
|
must either be zero or they must be pointers to inherited
|
||||||
@ -4191,7 +4255,7 @@ btr_store_big_rec_extern_fields_func(
|
|||||||
/* Either this must be an update in place,
|
/* Either this must be an update in place,
|
||||||
or the BLOB must be inherited, or the BLOB pointer
|
or the BLOB must be inherited, or the BLOB pointer
|
||||||
must be zero (will be written in this function). */
|
must be zero (will be written in this function). */
|
||||||
ut_a(update_in_place
|
ut_a(op == BTR_STORE_UPDATE
|
||||||
|| (field_ref[BTR_EXTERN_LEN] & BTR_EXTERN_INHERITED_FLAG)
|
|| (field_ref[BTR_EXTERN_LEN] & BTR_EXTERN_INHERITED_FLAG)
|
||||||
|| !memcmp(field_ref, field_ref_zero,
|
|| !memcmp(field_ref, field_ref_zero,
|
||||||
BTR_EXTERN_FIELD_REF_SIZE));
|
BTR_EXTERN_FIELD_REF_SIZE));
|
||||||
@ -4216,7 +4280,7 @@ btr_store_big_rec_extern_fields_func(
|
|||||||
|
|
||||||
prev_page_no = FIL_NULL;
|
prev_page_no = FIL_NULL;
|
||||||
|
|
||||||
if (UNIV_LIKELY_NULL(page_zip)) {
|
if (page_zip) {
|
||||||
int err = deflateReset(&c_stream);
|
int err = deflateReset(&c_stream);
|
||||||
ut_a(err == Z_OK);
|
ut_a(err == Z_OK);
|
||||||
|
|
||||||
@ -4236,18 +4300,24 @@ btr_store_big_rec_extern_fields_func(
|
|||||||
hint_page_no = prev_page_no + 1;
|
hint_page_no = prev_page_no + 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
alloc_another:
|
||||||
block = btr_page_alloc(index, hint_page_no,
|
block = btr_page_alloc(index, hint_page_no,
|
||||||
FSP_NO_DIR, 0, &mtr);
|
FSP_NO_DIR, 0, alloc_mtr, &mtr);
|
||||||
if (UNIV_UNLIKELY(block == NULL)) {
|
if (UNIV_UNLIKELY(block == NULL)) {
|
||||||
|
|
||||||
mtr_commit(&mtr);
|
mtr_commit(&mtr);
|
||||||
|
error = DB_OUT_OF_FILE_SPACE;
|
||||||
|
goto func_exit;
|
||||||
|
}
|
||||||
|
|
||||||
if (UNIV_LIKELY_NULL(page_zip)) {
|
if (rw_lock_get_x_lock_count(&block->lock) > 1) {
|
||||||
deflateEnd(&c_stream);
|
/* This page must have been freed in
|
||||||
mem_heap_free(heap);
|
btr_mtr previously. Put it aside, and
|
||||||
}
|
allocate another page for the BLOB data. */
|
||||||
|
ut_ad(alloc_mtr == btr_mtr);
|
||||||
return(DB_OUT_OF_FILE_SPACE);
|
ut_ad(btr_blob_op_is_update(op));
|
||||||
|
ut_ad(n_freed_pages < btr_mtr->n_freed_pages);
|
||||||
|
freed_pages[n_freed_pages++] = block;
|
||||||
|
goto alloc_another;
|
||||||
}
|
}
|
||||||
|
|
||||||
page_no = buf_block_get_page_no(block);
|
page_no = buf_block_get_page_no(block);
|
||||||
@ -4264,7 +4334,7 @@ btr_store_big_rec_extern_fields_func(
|
|||||||
SYNC_EXTERN_STORAGE);
|
SYNC_EXTERN_STORAGE);
|
||||||
prev_page = buf_block_get_frame(prev_block);
|
prev_page = buf_block_get_frame(prev_block);
|
||||||
|
|
||||||
if (UNIV_LIKELY_NULL(page_zip)) {
|
if (page_zip) {
|
||||||
mlog_write_ulint(
|
mlog_write_ulint(
|
||||||
prev_page + FIL_PAGE_NEXT,
|
prev_page + FIL_PAGE_NEXT,
|
||||||
page_no, MLOG_4BYTES, &mtr);
|
page_no, MLOG_4BYTES, &mtr);
|
||||||
@ -4281,7 +4351,7 @@ btr_store_big_rec_extern_fields_func(
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (UNIV_LIKELY_NULL(page_zip)) {
|
if (page_zip) {
|
||||||
int err;
|
int err;
|
||||||
page_zip_des_t* blob_page_zip;
|
page_zip_des_t* blob_page_zip;
|
||||||
|
|
||||||
@ -4364,11 +4434,15 @@ btr_store_big_rec_extern_fields_func(
|
|||||||
goto next_zip_page;
|
goto next_zip_page;
|
||||||
}
|
}
|
||||||
|
|
||||||
rec_block = buf_page_get(space_id, zip_size,
|
if (alloc_mtr == &mtr) {
|
||||||
rec_page_no,
|
rec_block = buf_page_get(
|
||||||
RW_X_LATCH, &mtr);
|
space_id, zip_size,
|
||||||
buf_block_dbg_add_level(rec_block,
|
rec_page_no,
|
||||||
SYNC_NO_ORDER_CHECK);
|
RW_X_LATCH, &mtr);
|
||||||
|
buf_block_dbg_add_level(
|
||||||
|
rec_block,
|
||||||
|
SYNC_NO_ORDER_CHECK);
|
||||||
|
}
|
||||||
|
|
||||||
if (err == Z_STREAM_END) {
|
if (err == Z_STREAM_END) {
|
||||||
mach_write_to_4(field_ref
|
mach_write_to_4(field_ref
|
||||||
@ -4402,7 +4476,8 @@ btr_store_big_rec_extern_fields_func(
|
|||||||
|
|
||||||
page_zip_write_blob_ptr(
|
page_zip_write_blob_ptr(
|
||||||
page_zip, rec, index, offsets,
|
page_zip, rec, index, offsets,
|
||||||
big_rec_vec->fields[i].field_no, &mtr);
|
big_rec_vec->fields[i].field_no,
|
||||||
|
alloc_mtr);
|
||||||
|
|
||||||
next_zip_page:
|
next_zip_page:
|
||||||
prev_page_no = page_no;
|
prev_page_no = page_no;
|
||||||
@ -4447,19 +4522,23 @@ next_zip_page:
|
|||||||
|
|
||||||
extern_len -= store_len;
|
extern_len -= store_len;
|
||||||
|
|
||||||
rec_block = buf_page_get(space_id, zip_size,
|
if (alloc_mtr == &mtr) {
|
||||||
rec_page_no,
|
rec_block = buf_page_get(
|
||||||
RW_X_LATCH, &mtr);
|
space_id, zip_size,
|
||||||
buf_block_dbg_add_level(rec_block,
|
rec_page_no,
|
||||||
SYNC_NO_ORDER_CHECK);
|
RW_X_LATCH, &mtr);
|
||||||
|
buf_block_dbg_add_level(
|
||||||
|
rec_block,
|
||||||
|
SYNC_NO_ORDER_CHECK);
|
||||||
|
}
|
||||||
|
|
||||||
mlog_write_ulint(field_ref + BTR_EXTERN_LEN, 0,
|
mlog_write_ulint(field_ref + BTR_EXTERN_LEN, 0,
|
||||||
MLOG_4BYTES, &mtr);
|
MLOG_4BYTES, alloc_mtr);
|
||||||
mlog_write_ulint(field_ref
|
mlog_write_ulint(field_ref
|
||||||
+ BTR_EXTERN_LEN + 4,
|
+ BTR_EXTERN_LEN + 4,
|
||||||
big_rec_vec->fields[i].len
|
big_rec_vec->fields[i].len
|
||||||
- extern_len,
|
- extern_len,
|
||||||
MLOG_4BYTES, &mtr);
|
MLOG_4BYTES, alloc_mtr);
|
||||||
|
|
||||||
if (prev_page_no == FIL_NULL) {
|
if (prev_page_no == FIL_NULL) {
|
||||||
btr_blob_dbg_add_blob(
|
btr_blob_dbg_add_blob(
|
||||||
@ -4469,18 +4548,19 @@ next_zip_page:
|
|||||||
|
|
||||||
mlog_write_ulint(field_ref
|
mlog_write_ulint(field_ref
|
||||||
+ BTR_EXTERN_SPACE_ID,
|
+ BTR_EXTERN_SPACE_ID,
|
||||||
space_id,
|
space_id, MLOG_4BYTES,
|
||||||
MLOG_4BYTES, &mtr);
|
alloc_mtr);
|
||||||
|
|
||||||
mlog_write_ulint(field_ref
|
mlog_write_ulint(field_ref
|
||||||
+ BTR_EXTERN_PAGE_NO,
|
+ BTR_EXTERN_PAGE_NO,
|
||||||
page_no,
|
page_no, MLOG_4BYTES,
|
||||||
MLOG_4BYTES, &mtr);
|
alloc_mtr);
|
||||||
|
|
||||||
mlog_write_ulint(field_ref
|
mlog_write_ulint(field_ref
|
||||||
+ BTR_EXTERN_OFFSET,
|
+ BTR_EXTERN_OFFSET,
|
||||||
FIL_PAGE_DATA,
|
FIL_PAGE_DATA,
|
||||||
MLOG_4BYTES, &mtr);
|
MLOG_4BYTES,
|
||||||
|
alloc_mtr);
|
||||||
}
|
}
|
||||||
|
|
||||||
prev_page_no = page_no;
|
prev_page_no = page_no;
|
||||||
@ -4494,8 +4574,23 @@ next_zip_page:
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (UNIV_LIKELY_NULL(page_zip)) {
|
func_exit:
|
||||||
|
if (page_zip) {
|
||||||
deflateEnd(&c_stream);
|
deflateEnd(&c_stream);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (n_freed_pages) {
|
||||||
|
ulint i;
|
||||||
|
|
||||||
|
ut_ad(alloc_mtr == btr_mtr);
|
||||||
|
ut_ad(btr_blob_op_is_update(op));
|
||||||
|
|
||||||
|
for (i = 0; i < n_freed_pages; i++) {
|
||||||
|
btr_page_free_low(index, freed_pages[i], 0, alloc_mtr);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (heap != NULL) {
|
||||||
mem_heap_free(heap);
|
mem_heap_free(heap);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -4516,7 +4611,7 @@ next_zip_page:
|
|||||||
ut_a(!(field_ref[BTR_EXTERN_LEN] & BTR_EXTERN_OWNER_FLAG));
|
ut_a(!(field_ref[BTR_EXTERN_LEN] & BTR_EXTERN_OWNER_FLAG));
|
||||||
}
|
}
|
||||||
#endif /* UNIV_DEBUG || UNIV_BLOB_LIGHT_DEBUG */
|
#endif /* UNIV_DEBUG || UNIV_BLOB_LIGHT_DEBUG */
|
||||||
return(DB_SUCCESS);
|
return(error);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*******************************************************************//**
|
/*******************************************************************//**
|
||||||
@ -4719,7 +4814,7 @@ btr_free_externally_stored_field(
|
|||||||
|
|
||||||
btr_page_free_low(index, ext_block, 0, &mtr);
|
btr_page_free_low(index, ext_block, 0, &mtr);
|
||||||
|
|
||||||
if (UNIV_LIKELY(page_zip != NULL)) {
|
if (page_zip) {
|
||||||
mach_write_to_4(field_ref + BTR_EXTERN_PAGE_NO,
|
mach_write_to_4(field_ref + BTR_EXTERN_PAGE_NO,
|
||||||
next_page_no);
|
next_page_no);
|
||||||
mach_write_to_4(field_ref + BTR_EXTERN_LEN + 4,
|
mach_write_to_4(field_ref + BTR_EXTERN_LEN + 4,
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
/*****************************************************************************
|
/*****************************************************************************
|
||||||
|
|
||||||
Copyright (c) 1995, 2011, Oracle and/or its affiliates. All Rights Reserved.
|
Copyright (c) 1995, 2012, Oracle and/or its affiliates. All Rights Reserved.
|
||||||
|
|
||||||
This program is free software; you can redistribute it and/or modify it under
|
This program is free software; you can redistribute it and/or modify it under
|
||||||
the terms of the GNU General Public License as published by the Free Software
|
the terms of the GNU General Public License as published by the Free Software
|
||||||
@ -250,28 +250,38 @@ fsp_fill_free_list(
|
|||||||
descriptor page and ibuf bitmap page;
|
descriptor page and ibuf bitmap page;
|
||||||
then we do not allocate more extents */
|
then we do not allocate more extents */
|
||||||
ulint space, /*!< in: space */
|
ulint space, /*!< in: space */
|
||||||
fsp_header_t* header, /*!< in: space header */
|
fsp_header_t* header, /*!< in/out: space header */
|
||||||
mtr_t* mtr); /*!< in: mtr */
|
mtr_t* mtr) /*!< in/out: mini-transaction */
|
||||||
|
__attribute__((nonnull));
|
||||||
/**********************************************************************//**
|
/**********************************************************************//**
|
||||||
Allocates a single free page from a segment. This function implements
|
Allocates a single free page from a segment. This function implements
|
||||||
the intelligent allocation strategy which tries to minimize file space
|
the intelligent allocation strategy which tries to minimize file space
|
||||||
fragmentation.
|
fragmentation.
|
||||||
@return the allocated page number, FIL_NULL if no page could be allocated */
|
@retval NULL if no page could be allocated
|
||||||
|
@retval block, rw_lock_x_lock_count(&block->lock) == 1 if allocation succeeded
|
||||||
|
(init_mtr == mtr, or the page was not previously freed in mtr)
|
||||||
|
@retval block (not allocated or initialized) otherwise */
|
||||||
static
|
static
|
||||||
ulint
|
buf_block_t*
|
||||||
fseg_alloc_free_page_low(
|
fseg_alloc_free_page_low(
|
||||||
/*=====================*/
|
/*=====================*/
|
||||||
ulint space, /*!< in: space */
|
ulint space, /*!< in: space */
|
||||||
ulint zip_size,/*!< in: compressed page size in bytes
|
ulint zip_size,/*!< in: compressed page size in bytes
|
||||||
or 0 for uncompressed pages */
|
or 0 for uncompressed pages */
|
||||||
fseg_inode_t* seg_inode, /*!< in: segment inode */
|
fseg_inode_t* seg_inode, /*!< in/out: segment inode */
|
||||||
ulint hint, /*!< in: hint of which page would be desirable */
|
ulint hint, /*!< in: hint of which page would be
|
||||||
|
desirable */
|
||||||
byte direction, /*!< in: if the new page is needed because
|
byte direction, /*!< in: if the new page is needed because
|
||||||
of an index page split, and records are
|
of an index page split, and records are
|
||||||
inserted there in order, into which
|
inserted there in order, into which
|
||||||
direction they go alphabetically: FSP_DOWN,
|
direction they go alphabetically: FSP_DOWN,
|
||||||
FSP_UP, FSP_NO_DIR */
|
FSP_UP, FSP_NO_DIR */
|
||||||
mtr_t* mtr); /*!< in: mtr handle */
|
mtr_t* mtr, /*!< in/out: mini-transaction */
|
||||||
|
mtr_t* init_mtr)/*!< in/out: mtr or another mini-transaction
|
||||||
|
in which the page should be initialized.
|
||||||
|
If init_mtr!=mtr, but the page is already
|
||||||
|
latched in mtr, do not initialize the page. */
|
||||||
|
__attribute__((warn_unused_result, nonnull));
|
||||||
#endif /* !UNIV_HOTBACKUP */
|
#endif /* !UNIV_HOTBACKUP */
|
||||||
|
|
||||||
/**********************************************************************//**
|
/**********************************************************************//**
|
||||||
@ -639,17 +649,18 @@ list, if not free limit == space size. This adding is necessary to make the
|
|||||||
descriptor defined, as they are uninitialized above the free limit.
|
descriptor defined, as they are uninitialized above the free limit.
|
||||||
@return pointer to the extent descriptor, NULL if the page does not
|
@return pointer to the extent descriptor, NULL if the page does not
|
||||||
exist in the space or if the offset exceeds the free limit */
|
exist in the space or if the offset exceeds the free limit */
|
||||||
UNIV_INLINE
|
UNIV_INLINE __attribute__((nonnull, warn_unused_result))
|
||||||
xdes_t*
|
xdes_t*
|
||||||
xdes_get_descriptor_with_space_hdr(
|
xdes_get_descriptor_with_space_hdr(
|
||||||
/*===============================*/
|
/*===============================*/
|
||||||
fsp_header_t* sp_header,/*!< in/out: space header, x-latched */
|
fsp_header_t* sp_header, /*!< in/out: space header, x-latched
|
||||||
ulint space, /*!< in: space id */
|
in mtr */
|
||||||
ulint offset, /*!< in: page offset;
|
ulint space, /*!< in: space id */
|
||||||
if equal to the free limit,
|
ulint offset, /*!< in: page offset; if equal
|
||||||
we try to add new extents to
|
to the free limit, we try to
|
||||||
the space free list */
|
add new extents to the space
|
||||||
mtr_t* mtr) /*!< in: mtr handle */
|
free list */
|
||||||
|
mtr_t* mtr) /*!< in/out: mini-transaction */
|
||||||
{
|
{
|
||||||
ulint limit;
|
ulint limit;
|
||||||
ulint size;
|
ulint size;
|
||||||
@ -657,11 +668,9 @@ xdes_get_descriptor_with_space_hdr(
|
|||||||
ulint descr_page_no;
|
ulint descr_page_no;
|
||||||
page_t* descr_page;
|
page_t* descr_page;
|
||||||
|
|
||||||
ut_ad(mtr);
|
|
||||||
ut_ad(mtr_memo_contains(mtr, fil_space_get_latch(space, NULL),
|
ut_ad(mtr_memo_contains(mtr, fil_space_get_latch(space, NULL),
|
||||||
MTR_MEMO_X_LOCK));
|
MTR_MEMO_X_LOCK));
|
||||||
ut_ad(mtr_memo_contains_page(mtr, sp_header, MTR_MEMO_PAGE_S_FIX)
|
ut_ad(mtr_memo_contains_page(mtr, sp_header, MTR_MEMO_PAGE_X_FIX));
|
||||||
|| mtr_memo_contains_page(mtr, sp_header, MTR_MEMO_PAGE_X_FIX));
|
|
||||||
ut_ad(page_offset(sp_header) == FSP_HEADER_OFFSET);
|
ut_ad(page_offset(sp_header) == FSP_HEADER_OFFSET);
|
||||||
/* Read free limit and space size */
|
/* Read free limit and space size */
|
||||||
limit = mach_read_from_4(sp_header + FSP_FREE_LIMIT);
|
limit = mach_read_from_4(sp_header + FSP_FREE_LIMIT);
|
||||||
@ -711,7 +720,7 @@ is necessary to make the descriptor defined, as they are uninitialized
|
|||||||
above the free limit.
|
above the free limit.
|
||||||
@return pointer to the extent descriptor, NULL if the page does not
|
@return pointer to the extent descriptor, NULL if the page does not
|
||||||
exist in the space or if the offset exceeds the free limit */
|
exist in the space or if the offset exceeds the free limit */
|
||||||
static
|
static __attribute__((nonnull, warn_unused_result))
|
||||||
xdes_t*
|
xdes_t*
|
||||||
xdes_get_descriptor(
|
xdes_get_descriptor(
|
||||||
/*================*/
|
/*================*/
|
||||||
@ -720,7 +729,7 @@ xdes_get_descriptor(
|
|||||||
or 0 for uncompressed pages */
|
or 0 for uncompressed pages */
|
||||||
ulint offset, /*!< in: page offset; if equal to the free limit,
|
ulint offset, /*!< in: page offset; if equal to the free limit,
|
||||||
we try to add new extents to the space free list */
|
we try to add new extents to the space free list */
|
||||||
mtr_t* mtr) /*!< in: mtr handle */
|
mtr_t* mtr) /*!< in/out: mini-transaction */
|
||||||
{
|
{
|
||||||
buf_block_t* block;
|
buf_block_t* block;
|
||||||
fsp_header_t* sp_header;
|
fsp_header_t* sp_header;
|
||||||
@ -1098,14 +1107,14 @@ fsp_header_get_tablespace_size(void)
|
|||||||
Tries to extend a single-table tablespace so that a page would fit in the
|
Tries to extend a single-table tablespace so that a page would fit in the
|
||||||
data file.
|
data file.
|
||||||
@return TRUE if success */
|
@return TRUE if success */
|
||||||
static
|
static __attribute__((nonnull, warn_unused_result))
|
||||||
ibool
|
ibool
|
||||||
fsp_try_extend_data_file_with_pages(
|
fsp_try_extend_data_file_with_pages(
|
||||||
/*================================*/
|
/*================================*/
|
||||||
ulint space, /*!< in: space */
|
ulint space, /*!< in: space */
|
||||||
ulint page_no, /*!< in: page number */
|
ulint page_no, /*!< in: page number */
|
||||||
fsp_header_t* header, /*!< in: space header */
|
fsp_header_t* header, /*!< in/out: space header */
|
||||||
mtr_t* mtr) /*!< in: mtr */
|
mtr_t* mtr) /*!< in/out: mini-transaction */
|
||||||
{
|
{
|
||||||
ibool success;
|
ibool success;
|
||||||
ulint actual_size;
|
ulint actual_size;
|
||||||
@ -1130,7 +1139,7 @@ fsp_try_extend_data_file_with_pages(
|
|||||||
/***********************************************************************//**
|
/***********************************************************************//**
|
||||||
Tries to extend the last data file of a tablespace if it is auto-extending.
|
Tries to extend the last data file of a tablespace if it is auto-extending.
|
||||||
@return FALSE if not auto-extending */
|
@return FALSE if not auto-extending */
|
||||||
static
|
static __attribute__((nonnull))
|
||||||
ibool
|
ibool
|
||||||
fsp_try_extend_data_file(
|
fsp_try_extend_data_file(
|
||||||
/*=====================*/
|
/*=====================*/
|
||||||
@ -1140,8 +1149,8 @@ fsp_try_extend_data_file(
|
|||||||
the actual file size rounded down to
|
the actual file size rounded down to
|
||||||
megabyte */
|
megabyte */
|
||||||
ulint space, /*!< in: space */
|
ulint space, /*!< in: space */
|
||||||
fsp_header_t* header, /*!< in: space header */
|
fsp_header_t* header, /*!< in/out: space header */
|
||||||
mtr_t* mtr) /*!< in: mtr */
|
mtr_t* mtr) /*!< in/out: mini-transaction */
|
||||||
{
|
{
|
||||||
ulint size;
|
ulint size;
|
||||||
ulint zip_size;
|
ulint zip_size;
|
||||||
@ -1277,7 +1286,7 @@ fsp_fill_free_list(
|
|||||||
then we do not allocate more extents */
|
then we do not allocate more extents */
|
||||||
ulint space, /*!< in: space */
|
ulint space, /*!< in: space */
|
||||||
fsp_header_t* header, /*!< in/out: space header */
|
fsp_header_t* header, /*!< in/out: space header */
|
||||||
mtr_t* mtr) /*!< in: mtr */
|
mtr_t* mtr) /*!< in/out: mini-transaction */
|
||||||
{
|
{
|
||||||
ulint limit;
|
ulint limit;
|
||||||
ulint size;
|
ulint size;
|
||||||
@ -1476,29 +1485,120 @@ fsp_alloc_free_extent(
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**********************************************************************//**
|
/**********************************************************************//**
|
||||||
Allocates a single free page from a space. The page is marked as used.
|
Allocates a single free page from a space. */
|
||||||
@return the page offset, FIL_NULL if no page could be allocated */
|
static __attribute__((nonnull))
|
||||||
|
void
|
||||||
|
fsp_alloc_from_free_frag(
|
||||||
|
/*=====================*/
|
||||||
|
fsp_header_t* header, /*!< in/out: tablespace header */
|
||||||
|
xdes_t* descr, /*!< in/out: extent descriptor */
|
||||||
|
ulint bit, /*!< in: slot to allocate in the extent */
|
||||||
|
mtr_t* mtr) /*!< in/out: mini-transaction */
|
||||||
|
{
|
||||||
|
ulint frag_n_used;
|
||||||
|
|
||||||
|
ut_ad(xdes_get_state(descr, mtr) == XDES_FREE_FRAG);
|
||||||
|
ut_a(xdes_get_bit(descr, XDES_FREE_BIT, bit, mtr));
|
||||||
|
xdes_set_bit(descr, XDES_FREE_BIT, bit, FALSE, mtr);
|
||||||
|
|
||||||
|
/* Update the FRAG_N_USED field */
|
||||||
|
frag_n_used = mtr_read_ulint(header + FSP_FRAG_N_USED, MLOG_4BYTES,
|
||||||
|
mtr);
|
||||||
|
frag_n_used++;
|
||||||
|
mlog_write_ulint(header + FSP_FRAG_N_USED, frag_n_used, MLOG_4BYTES,
|
||||||
|
mtr);
|
||||||
|
if (xdes_is_full(descr, mtr)) {
|
||||||
|
/* The fragment is full: move it to another list */
|
||||||
|
flst_remove(header + FSP_FREE_FRAG, descr + XDES_FLST_NODE,
|
||||||
|
mtr);
|
||||||
|
xdes_set_state(descr, XDES_FULL_FRAG, mtr);
|
||||||
|
|
||||||
|
flst_add_last(header + FSP_FULL_FRAG, descr + XDES_FLST_NODE,
|
||||||
|
mtr);
|
||||||
|
mlog_write_ulint(header + FSP_FRAG_N_USED,
|
||||||
|
frag_n_used - FSP_EXTENT_SIZE, MLOG_4BYTES,
|
||||||
|
mtr);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**********************************************************************//**
|
||||||
|
Gets a buffer block for an allocated page.
|
||||||
|
|
||||||
|
NOTE: If init_mtr != mtr, the block will only be initialized if it was
|
||||||
|
not previously x-latched. It is assumed that the block has been
|
||||||
|
x-latched only by mtr, and freed in mtr in that case.
|
||||||
|
|
||||||
|
@return block, initialized if init_mtr==mtr
|
||||||
|
or rw_lock_x_lock_count(&block->lock) == 1 */
|
||||||
static
|
static
|
||||||
ulint
|
buf_block_t*
|
||||||
|
fsp_page_create(
|
||||||
|
/*============*/
|
||||||
|
ulint space, /*!< in: space id of the allocated page */
|
||||||
|
ulint zip_size, /*!< in: compressed page size in bytes
|
||||||
|
or 0 for uncompressed pages */
|
||||||
|
ulint page_no, /*!< in: page number of the allocated page */
|
||||||
|
mtr_t* mtr, /*!< in: mini-transaction of the allocation */
|
||||||
|
mtr_t* init_mtr) /*!< in: mini-transaction for initializing
|
||||||
|
the page */
|
||||||
|
{
|
||||||
|
buf_block_t* block
|
||||||
|
= buf_page_create(space, page_no, zip_size, init_mtr);
|
||||||
|
#ifdef UNIV_SYNC_DEBUG
|
||||||
|
ut_ad(mtr_memo_contains(mtr, block, MTR_MEMO_PAGE_X_FIX)
|
||||||
|
== rw_lock_own(&block->lock, RW_LOCK_EX));
|
||||||
|
#endif /* UNIV_SYNC_DEBUG */
|
||||||
|
|
||||||
|
/* Mimic buf_page_get(), but avoid the buf_pool->page_hash lookup. */
|
||||||
|
rw_lock_x_lock(&block->lock);
|
||||||
|
mutex_enter(&block->mutex);
|
||||||
|
buf_block_buf_fix_inc(block, __FILE__, __LINE__);
|
||||||
|
mutex_exit(&block->mutex);
|
||||||
|
mtr_memo_push(init_mtr, block, MTR_MEMO_PAGE_X_FIX);
|
||||||
|
|
||||||
|
if (init_mtr == mtr
|
||||||
|
|| rw_lock_get_x_lock_count(&block->lock) == 1) {
|
||||||
|
|
||||||
|
/* Initialize the page, unless it was already
|
||||||
|
X-latched in mtr. (In this case, we would want to
|
||||||
|
allocate another page that has not been freed in mtr.) */
|
||||||
|
ut_ad(init_mtr == mtr
|
||||||
|
|| !mtr_memo_contains(mtr, block, MTR_MEMO_PAGE_X_FIX));
|
||||||
|
|
||||||
|
fsp_init_file_page(block, init_mtr);
|
||||||
|
}
|
||||||
|
|
||||||
|
return(block);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**********************************************************************//**
|
||||||
|
Allocates a single free page from a space. The page is marked as used.
|
||||||
|
@retval NULL if no page could be allocated
|
||||||
|
@retval block, rw_lock_x_lock_count(&block->lock) == 1 if allocation succeeded
|
||||||
|
(init_mtr == mtr, or the page was not previously freed in mtr)
|
||||||
|
@retval block (not allocated or initialized) otherwise */
|
||||||
|
static __attribute__((nonnull, warn_unused_result))
|
||||||
|
buf_block_t*
|
||||||
fsp_alloc_free_page(
|
fsp_alloc_free_page(
|
||||||
/*================*/
|
/*================*/
|
||||||
ulint space, /*!< in: space id */
|
ulint space, /*!< in: space id */
|
||||||
ulint zip_size,/*!< in: compressed page size in bytes
|
ulint zip_size,/*!< in: compressed page size in bytes
|
||||||
or 0 for uncompressed pages */
|
or 0 for uncompressed pages */
|
||||||
ulint hint, /*!< in: hint of which page would be desirable */
|
ulint hint, /*!< in: hint of which page would be desirable */
|
||||||
mtr_t* mtr) /*!< in: mtr handle */
|
mtr_t* mtr, /*!< in/out: mini-transaction */
|
||||||
|
mtr_t* init_mtr)/*!< in/out: mini-transaction in which the
|
||||||
|
page should be initialized
|
||||||
|
(may be the same as mtr) */
|
||||||
{
|
{
|
||||||
fsp_header_t* header;
|
fsp_header_t* header;
|
||||||
fil_addr_t first;
|
fil_addr_t first;
|
||||||
xdes_t* descr;
|
xdes_t* descr;
|
||||||
buf_block_t* block;
|
|
||||||
ulint free;
|
ulint free;
|
||||||
ulint frag_n_used;
|
|
||||||
ulint page_no;
|
ulint page_no;
|
||||||
ulint space_size;
|
ulint space_size;
|
||||||
ibool success;
|
|
||||||
|
|
||||||
ut_ad(mtr);
|
ut_ad(mtr);
|
||||||
|
ut_ad(init_mtr);
|
||||||
|
|
||||||
header = fsp_get_space_header(space, zip_size, mtr);
|
header = fsp_get_space_header(space, zip_size, mtr);
|
||||||
|
|
||||||
@ -1525,7 +1625,7 @@ fsp_alloc_free_page(
|
|||||||
if (descr == NULL) {
|
if (descr == NULL) {
|
||||||
/* No free space left */
|
/* No free space left */
|
||||||
|
|
||||||
return(FIL_NULL);
|
return(NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
xdes_set_state(descr, XDES_FREE_FRAG, mtr);
|
xdes_set_state(descr, XDES_FREE_FRAG, mtr);
|
||||||
@ -1570,50 +1670,18 @@ fsp_alloc_free_page(
|
|||||||
" space size %lu. Page no %lu.\n",
|
" space size %lu. Page no %lu.\n",
|
||||||
(ulong) space, (ulong) space_size,
|
(ulong) space, (ulong) space_size,
|
||||||
(ulong) page_no);
|
(ulong) page_no);
|
||||||
return(FIL_NULL);
|
return(NULL);
|
||||||
}
|
}
|
||||||
success = fsp_try_extend_data_file_with_pages(space, page_no,
|
if (!fsp_try_extend_data_file_with_pages(space, page_no,
|
||||||
header, mtr);
|
header, mtr)) {
|
||||||
if (!success) {
|
|
||||||
/* No disk space left */
|
/* No disk space left */
|
||||||
return(FIL_NULL);
|
return(NULL);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
xdes_set_bit(descr, XDES_FREE_BIT, free, FALSE, mtr);
|
fsp_alloc_from_free_frag(header, descr, free, mtr);
|
||||||
|
|
||||||
/* Update the FRAG_N_USED field */
|
return(fsp_page_create(space, zip_size, page_no, mtr, init_mtr));
|
||||||
frag_n_used = mtr_read_ulint(header + FSP_FRAG_N_USED, MLOG_4BYTES,
|
|
||||||
mtr);
|
|
||||||
frag_n_used++;
|
|
||||||
mlog_write_ulint(header + FSP_FRAG_N_USED, frag_n_used, MLOG_4BYTES,
|
|
||||||
mtr);
|
|
||||||
if (xdes_is_full(descr, mtr)) {
|
|
||||||
/* The fragment is full: move it to another list */
|
|
||||||
flst_remove(header + FSP_FREE_FRAG, descr + XDES_FLST_NODE,
|
|
||||||
mtr);
|
|
||||||
xdes_set_state(descr, XDES_FULL_FRAG, mtr);
|
|
||||||
|
|
||||||
flst_add_last(header + FSP_FULL_FRAG, descr + XDES_FLST_NODE,
|
|
||||||
mtr);
|
|
||||||
mlog_write_ulint(header + FSP_FRAG_N_USED,
|
|
||||||
frag_n_used - FSP_EXTENT_SIZE, MLOG_4BYTES,
|
|
||||||
mtr);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Initialize the allocated page to the buffer pool, so that it can
|
|
||||||
be obtained immediately with buf_page_get without need for a disk
|
|
||||||
read. */
|
|
||||||
|
|
||||||
buf_page_create(space, page_no, zip_size, mtr);
|
|
||||||
|
|
||||||
block = buf_page_get(space, zip_size, page_no, RW_X_LATCH, mtr);
|
|
||||||
buf_block_dbg_add_level(block, SYNC_FSP_PAGE);
|
|
||||||
|
|
||||||
/* Prior contents of the page should be ignored */
|
|
||||||
fsp_init_file_page(block, mtr);
|
|
||||||
|
|
||||||
return(page_no);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**********************************************************************//**
|
/**********************************************************************//**
|
||||||
@ -1652,6 +1720,9 @@ fsp_free_page(
|
|||||||
fputs("InnoDB: Dump of descriptor: ", stderr);
|
fputs("InnoDB: Dump of descriptor: ", stderr);
|
||||||
ut_print_buf(stderr, ((byte*)descr) - 50, 200);
|
ut_print_buf(stderr, ((byte*)descr) - 50, 200);
|
||||||
putc('\n', stderr);
|
putc('\n', stderr);
|
||||||
|
/* Crash in debug version, so that we get a core dump
|
||||||
|
of this corruption. */
|
||||||
|
ut_ad(0);
|
||||||
|
|
||||||
if (state == XDES_FREE) {
|
if (state == XDES_FREE) {
|
||||||
/* We put here some fault tolerance: if the page
|
/* We put here some fault tolerance: if the page
|
||||||
@ -1670,6 +1741,9 @@ fsp_free_page(
|
|||||||
"InnoDB: Dump of descriptor: ", (ulong) page);
|
"InnoDB: Dump of descriptor: ", (ulong) page);
|
||||||
ut_print_buf(stderr, ((byte*)descr) - 50, 200);
|
ut_print_buf(stderr, ((byte*)descr) - 50, 200);
|
||||||
putc('\n', stderr);
|
putc('\n', stderr);
|
||||||
|
/* Crash in debug version, so that we get a core dump
|
||||||
|
of this corruption. */
|
||||||
|
ut_ad(0);
|
||||||
|
|
||||||
/* We put here some fault tolerance: if the page
|
/* We put here some fault tolerance: if the page
|
||||||
is already free, return without doing anything! */
|
is already free, return without doing anything! */
|
||||||
@ -1704,6 +1778,8 @@ fsp_free_page(
|
|||||||
mtr);
|
mtr);
|
||||||
fsp_free_extent(space, zip_size, page, mtr);
|
fsp_free_extent(space, zip_size, page, mtr);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
mtr->n_freed_pages++;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**********************************************************************//**
|
/**********************************************************************//**
|
||||||
@ -1836,7 +1912,6 @@ fsp_alloc_seg_inode_page(
|
|||||||
fseg_inode_t* inode;
|
fseg_inode_t* inode;
|
||||||
buf_block_t* block;
|
buf_block_t* block;
|
||||||
page_t* page;
|
page_t* page;
|
||||||
ulint page_no;
|
|
||||||
ulint space;
|
ulint space;
|
||||||
ulint zip_size;
|
ulint zip_size;
|
||||||
ulint i;
|
ulint i;
|
||||||
@ -1847,15 +1922,15 @@ fsp_alloc_seg_inode_page(
|
|||||||
zip_size = dict_table_flags_to_zip_size(
|
zip_size = dict_table_flags_to_zip_size(
|
||||||
mach_read_from_4(FSP_SPACE_FLAGS + space_header));
|
mach_read_from_4(FSP_SPACE_FLAGS + space_header));
|
||||||
|
|
||||||
page_no = fsp_alloc_free_page(space, zip_size, 0, mtr);
|
block = fsp_alloc_free_page(space, zip_size, 0, mtr, mtr);
|
||||||
|
|
||||||
if (page_no == FIL_NULL) {
|
if (block == NULL) {
|
||||||
|
|
||||||
return(FALSE);
|
return(FALSE);
|
||||||
}
|
}
|
||||||
|
|
||||||
block = buf_page_get(space, zip_size, page_no, RW_X_LATCH, mtr);
|
|
||||||
buf_block_dbg_add_level(block, SYNC_FSP_PAGE);
|
buf_block_dbg_add_level(block, SYNC_FSP_PAGE);
|
||||||
|
ut_ad(rw_lock_get_x_lock_count(&block->lock) == 1);
|
||||||
|
|
||||||
block->check_index_page_at_flush = FALSE;
|
block->check_index_page_at_flush = FALSE;
|
||||||
|
|
||||||
@ -2258,19 +2333,20 @@ fseg_create_general(
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (page == 0) {
|
if (page == 0) {
|
||||||
page = fseg_alloc_free_page_low(space, zip_size,
|
block = fseg_alloc_free_page_low(space, zip_size,
|
||||||
inode, 0, FSP_UP, mtr);
|
inode, 0, FSP_UP, mtr, mtr);
|
||||||
|
|
||||||
if (page == FIL_NULL) {
|
if (block == NULL) {
|
||||||
|
|
||||||
fsp_free_seg_inode(space, zip_size, inode, mtr);
|
fsp_free_seg_inode(space, zip_size, inode, mtr);
|
||||||
|
|
||||||
goto funct_exit;
|
goto funct_exit;
|
||||||
}
|
}
|
||||||
|
|
||||||
block = buf_page_get(space, zip_size, page, RW_X_LATCH, mtr);
|
ut_ad(rw_lock_get_x_lock_count(&block->lock) == 1);
|
||||||
|
|
||||||
header = byte_offset + buf_block_get_frame(block);
|
header = byte_offset + buf_block_get_frame(block);
|
||||||
mlog_write_ulint(header - byte_offset + FIL_PAGE_TYPE,
|
mlog_write_ulint(buf_block_get_frame(block) + FIL_PAGE_TYPE,
|
||||||
FIL_PAGE_TYPE_SYS, MLOG_2BYTES, mtr);
|
FIL_PAGE_TYPE_SYS, MLOG_2BYTES, mtr);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2447,8 +2523,10 @@ fseg_fill_free_list(
|
|||||||
Allocates a free extent for the segment: looks first in the free list of the
|
Allocates a free extent for the segment: looks first in the free list of the
|
||||||
segment, then tries to allocate from the space free list. NOTE that the extent
|
segment, then tries to allocate from the space free list. NOTE that the extent
|
||||||
returned still resides in the segment free list, it is not yet taken off it!
|
returned still resides in the segment free list, it is not yet taken off it!
|
||||||
@return allocated extent, still placed in the segment free list, NULL
|
@retval NULL if no page could be allocated
|
||||||
if could not be allocated */
|
@retval block, rw_lock_x_lock_count(&block->lock) == 1 if allocation succeeded
|
||||||
|
(init_mtr == mtr, or the page was not previously freed in mtr)
|
||||||
|
@retval block (not allocated or initialized) otherwise */
|
||||||
static
|
static
|
||||||
xdes_t*
|
xdes_t*
|
||||||
fseg_alloc_free_extent(
|
fseg_alloc_free_extent(
|
||||||
@ -2500,22 +2578,30 @@ fseg_alloc_free_extent(
|
|||||||
Allocates a single free page from a segment. This function implements
|
Allocates a single free page from a segment. This function implements
|
||||||
the intelligent allocation strategy which tries to minimize file space
|
the intelligent allocation strategy which tries to minimize file space
|
||||||
fragmentation.
|
fragmentation.
|
||||||
@return the allocated page number, FIL_NULL if no page could be allocated */
|
@retval NULL if no page could be allocated
|
||||||
|
@retval block, rw_lock_x_lock_count(&block->lock) == 1 if allocation succeeded
|
||||||
|
(init_mtr == mtr, or the page was not previously freed in mtr)
|
||||||
|
@retval block (not allocated or initialized) otherwise */
|
||||||
static
|
static
|
||||||
ulint
|
buf_block_t*
|
||||||
fseg_alloc_free_page_low(
|
fseg_alloc_free_page_low(
|
||||||
/*=====================*/
|
/*=====================*/
|
||||||
ulint space, /*!< in: space */
|
ulint space, /*!< in: space */
|
||||||
ulint zip_size,/*!< in: compressed page size in bytes
|
ulint zip_size,/*!< in: compressed page size in bytes
|
||||||
or 0 for uncompressed pages */
|
or 0 for uncompressed pages */
|
||||||
fseg_inode_t* seg_inode, /*!< in: segment inode */
|
fseg_inode_t* seg_inode, /*!< in/out: segment inode */
|
||||||
ulint hint, /*!< in: hint of which page would be desirable */
|
ulint hint, /*!< in: hint of which page would be
|
||||||
|
desirable */
|
||||||
byte direction, /*!< in: if the new page is needed because
|
byte direction, /*!< in: if the new page is needed because
|
||||||
of an index page split, and records are
|
of an index page split, and records are
|
||||||
inserted there in order, into which
|
inserted there in order, into which
|
||||||
direction they go alphabetically: FSP_DOWN,
|
direction they go alphabetically: FSP_DOWN,
|
||||||
FSP_UP, FSP_NO_DIR */
|
FSP_UP, FSP_NO_DIR */
|
||||||
mtr_t* mtr) /*!< in: mtr handle */
|
mtr_t* mtr, /*!< in/out: mini-transaction */
|
||||||
|
mtr_t* init_mtr)/*!< in/out: mtr or another mini-transaction
|
||||||
|
in which the page should be initialized.
|
||||||
|
If init_mtr!=mtr, but the page is already
|
||||||
|
latched in mtr, do not initialize the page. */
|
||||||
{
|
{
|
||||||
fsp_header_t* space_header;
|
fsp_header_t* space_header;
|
||||||
ulint space_size;
|
ulint space_size;
|
||||||
@ -2526,7 +2612,6 @@ fseg_alloc_free_page_low(
|
|||||||
ulint ret_page; /*!< the allocated page offset, FIL_NULL
|
ulint ret_page; /*!< the allocated page offset, FIL_NULL
|
||||||
if could not be allocated */
|
if could not be allocated */
|
||||||
xdes_t* ret_descr; /*!< the extent of the allocated page */
|
xdes_t* ret_descr; /*!< the extent of the allocated page */
|
||||||
ibool frag_page_allocated = FALSE;
|
|
||||||
ibool success;
|
ibool success;
|
||||||
ulint n;
|
ulint n;
|
||||||
|
|
||||||
@ -2548,6 +2633,7 @@ fseg_alloc_free_page_low(
|
|||||||
if (descr == NULL) {
|
if (descr == NULL) {
|
||||||
/* Hint outside space or too high above free limit: reset
|
/* Hint outside space or too high above free limit: reset
|
||||||
hint */
|
hint */
|
||||||
|
/* The file space header page is always allocated. */
|
||||||
hint = 0;
|
hint = 0;
|
||||||
descr = xdes_get_descriptor(space, zip_size, hint, mtr);
|
descr = xdes_get_descriptor(space, zip_size, hint, mtr);
|
||||||
}
|
}
|
||||||
@ -2558,15 +2644,19 @@ fseg_alloc_free_page_low(
|
|||||||
&& mach_read_from_8(descr + XDES_ID) == seg_id
|
&& mach_read_from_8(descr + XDES_ID) == seg_id
|
||||||
&& (xdes_get_bit(descr, XDES_FREE_BIT,
|
&& (xdes_get_bit(descr, XDES_FREE_BIT,
|
||||||
hint % FSP_EXTENT_SIZE, mtr) == TRUE)) {
|
hint % FSP_EXTENT_SIZE, mtr) == TRUE)) {
|
||||||
|
take_hinted_page:
|
||||||
/* 1. We can take the hinted page
|
/* 1. We can take the hinted page
|
||||||
=================================*/
|
=================================*/
|
||||||
ret_descr = descr;
|
ret_descr = descr;
|
||||||
ret_page = hint;
|
ret_page = hint;
|
||||||
|
/* Skip the check for extending the tablespace. If the
|
||||||
|
page hint were not within the size of the tablespace,
|
||||||
|
we would have got (descr == NULL) above and reset the hint. */
|
||||||
|
goto got_hinted_page;
|
||||||
/*-----------------------------------------------------------*/
|
/*-----------------------------------------------------------*/
|
||||||
} else if ((xdes_get_state(descr, mtr) == XDES_FREE)
|
} else if (xdes_get_state(descr, mtr) == XDES_FREE
|
||||||
&& ((reserved - used) < reserved / FSEG_FILLFACTOR)
|
&& reserved - used < reserved / FSEG_FILLFACTOR
|
||||||
&& (used >= FSEG_FRAG_LIMIT)) {
|
&& used >= FSEG_FRAG_LIMIT) {
|
||||||
|
|
||||||
/* 2. We allocate the free extent from space and can take
|
/* 2. We allocate the free extent from space and can take
|
||||||
=========================================================
|
=========================================================
|
||||||
@ -2584,7 +2674,7 @@ fseg_alloc_free_page_low(
|
|||||||
/* Try to fill the segment free list */
|
/* Try to fill the segment free list */
|
||||||
fseg_fill_free_list(seg_inode, space, zip_size,
|
fseg_fill_free_list(seg_inode, space, zip_size,
|
||||||
hint + FSP_EXTENT_SIZE, mtr);
|
hint + FSP_EXTENT_SIZE, mtr);
|
||||||
ret_page = hint;
|
goto take_hinted_page;
|
||||||
/*-----------------------------------------------------------*/
|
/*-----------------------------------------------------------*/
|
||||||
} else if ((direction != FSP_NO_DIR)
|
} else if ((direction != FSP_NO_DIR)
|
||||||
&& ((reserved - used) < reserved / FSEG_FILLFACTOR)
|
&& ((reserved - used) < reserved / FSEG_FILLFACTOR)
|
||||||
@ -2632,7 +2722,7 @@ fseg_alloc_free_page_low(
|
|||||||
first = flst_get_first(seg_inode + FSEG_FREE, mtr);
|
first = flst_get_first(seg_inode + FSEG_FREE, mtr);
|
||||||
} else {
|
} else {
|
||||||
ut_error;
|
ut_error;
|
||||||
return(FIL_NULL);
|
return(NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
ret_descr = xdes_lst_get_descriptor(space, zip_size,
|
ret_descr = xdes_lst_get_descriptor(space, zip_size,
|
||||||
@ -2644,20 +2734,23 @@ fseg_alloc_free_page_low(
|
|||||||
} else if (used < FSEG_FRAG_LIMIT) {
|
} else if (used < FSEG_FRAG_LIMIT) {
|
||||||
/* 6. We allocate an individual page from the space
|
/* 6. We allocate an individual page from the space
|
||||||
===================================================*/
|
===================================================*/
|
||||||
ret_page = fsp_alloc_free_page(space, zip_size, hint, mtr);
|
buf_block_t* block = fsp_alloc_free_page(
|
||||||
ret_descr = NULL;
|
space, zip_size, hint, mtr, init_mtr);
|
||||||
|
|
||||||
frag_page_allocated = TRUE;
|
if (block != NULL) {
|
||||||
|
|
||||||
if (ret_page != FIL_NULL) {
|
|
||||||
/* Put the page in the fragment page array of the
|
/* Put the page in the fragment page array of the
|
||||||
segment */
|
segment */
|
||||||
n = fseg_find_free_frag_page_slot(seg_inode, mtr);
|
n = fseg_find_free_frag_page_slot(seg_inode, mtr);
|
||||||
ut_a(n != FIL_NULL);
|
ut_a(n != ULINT_UNDEFINED);
|
||||||
|
|
||||||
fseg_set_nth_frag_page_no(seg_inode, n, ret_page,
|
fseg_set_nth_frag_page_no(
|
||||||
mtr);
|
seg_inode, n, buf_block_get_page_no(block),
|
||||||
|
mtr);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* fsp_alloc_free_page() invoked fsp_init_file_page()
|
||||||
|
already. */
|
||||||
|
return(block);
|
||||||
/*-----------------------------------------------------------*/
|
/*-----------------------------------------------------------*/
|
||||||
} else {
|
} else {
|
||||||
/* 7. We allocate a new extent and take its first page
|
/* 7. We allocate a new extent and take its first page
|
||||||
@ -2675,7 +2768,7 @@ fseg_alloc_free_page_low(
|
|||||||
if (ret_page == FIL_NULL) {
|
if (ret_page == FIL_NULL) {
|
||||||
/* Page could not be allocated */
|
/* Page could not be allocated */
|
||||||
|
|
||||||
return(FIL_NULL);
|
return(NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (space != 0) {
|
if (space != 0) {
|
||||||
@ -2693,38 +2786,22 @@ fseg_alloc_free_page_low(
|
|||||||
" the space size %lu. Page no %lu.\n",
|
" the space size %lu. Page no %lu.\n",
|
||||||
(ulong) space, (ulong) space_size,
|
(ulong) space, (ulong) space_size,
|
||||||
(ulong) ret_page);
|
(ulong) ret_page);
|
||||||
return(FIL_NULL);
|
return(NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
success = fsp_try_extend_data_file_with_pages(
|
success = fsp_try_extend_data_file_with_pages(
|
||||||
space, ret_page, space_header, mtr);
|
space, ret_page, space_header, mtr);
|
||||||
if (!success) {
|
if (!success) {
|
||||||
/* No disk space left */
|
/* No disk space left */
|
||||||
return(FIL_NULL);
|
return(NULL);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!frag_page_allocated) {
|
got_hinted_page:
|
||||||
/* Initialize the allocated page to buffer pool, so that it
|
/* ret_descr == NULL if the block was allocated from free_frag
|
||||||
can be obtained immediately with buf_page_get without need
|
(XDES_FREE_FRAG) */
|
||||||
for a disk read */
|
if (ret_descr != NULL) {
|
||||||
buf_block_t* block;
|
|
||||||
ulint zip_size = dict_table_flags_to_zip_size(
|
|
||||||
mach_read_from_4(FSP_SPACE_FLAGS + space_header));
|
|
||||||
|
|
||||||
block = buf_page_create(space, ret_page, zip_size, mtr);
|
|
||||||
buf_block_dbg_add_level(block, SYNC_FSP_PAGE);
|
|
||||||
|
|
||||||
if (UNIV_UNLIKELY(block != buf_page_get(space, zip_size,
|
|
||||||
ret_page, RW_X_LATCH,
|
|
||||||
mtr))) {
|
|
||||||
ut_error;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* The prior contents of the page should be ignored */
|
|
||||||
fsp_init_file_page(block, mtr);
|
|
||||||
|
|
||||||
/* At this point we know the extent and the page offset.
|
/* At this point we know the extent and the page offset.
|
||||||
The extent is still in the appropriate list (FSEG_NOT_FULL
|
The extent is still in the appropriate list (FSEG_NOT_FULL
|
||||||
or FSEG_FREE), and the page is not yet marked as used. */
|
or FSEG_FREE), and the page is not yet marked as used. */
|
||||||
@ -2737,22 +2814,28 @@ fseg_alloc_free_page_low(
|
|||||||
fseg_mark_page_used(seg_inode, space, zip_size, ret_page, mtr);
|
fseg_mark_page_used(seg_inode, space, zip_size, ret_page, mtr);
|
||||||
}
|
}
|
||||||
|
|
||||||
buf_reset_check_index_page_at_flush(space, ret_page);
|
return(fsp_page_create(
|
||||||
|
space, dict_table_flags_to_zip_size(
|
||||||
return(ret_page);
|
mach_read_from_4(FSP_SPACE_FLAGS
|
||||||
|
+ space_header)),
|
||||||
|
ret_page, mtr, init_mtr));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**********************************************************************//**
|
/**********************************************************************//**
|
||||||
Allocates a single free page from a segment. This function implements
|
Allocates a single free page from a segment. This function implements
|
||||||
the intelligent allocation strategy which tries to minimize file space
|
the intelligent allocation strategy which tries to minimize file space
|
||||||
fragmentation.
|
fragmentation.
|
||||||
@return allocated page offset, FIL_NULL if no page could be allocated */
|
@retval NULL if no page could be allocated
|
||||||
|
@retval block, rw_lock_x_lock_count(&block->lock) == 1 if allocation succeeded
|
||||||
|
(init_mtr == mtr, or the page was not previously freed in mtr)
|
||||||
|
@retval block (not allocated or initialized) otherwise */
|
||||||
UNIV_INTERN
|
UNIV_INTERN
|
||||||
ulint
|
buf_block_t*
|
||||||
fseg_alloc_free_page_general(
|
fseg_alloc_free_page_general(
|
||||||
/*=========================*/
|
/*=========================*/
|
||||||
fseg_header_t* seg_header,/*!< in: segment header */
|
fseg_header_t* seg_header,/*!< in/out: segment header */
|
||||||
ulint hint, /*!< in: hint of which page would be desirable */
|
ulint hint, /*!< in: hint of which page would be
|
||||||
|
desirable */
|
||||||
byte direction,/*!< in: if the new page is needed because
|
byte direction,/*!< in: if the new page is needed because
|
||||||
of an index page split, and records are
|
of an index page split, and records are
|
||||||
inserted there in order, into which
|
inserted there in order, into which
|
||||||
@ -2763,15 +2846,18 @@ fseg_alloc_free_page_general(
|
|||||||
with fsp_reserve_free_extents, then there
|
with fsp_reserve_free_extents, then there
|
||||||
is no need to do the check for this individual
|
is no need to do the check for this individual
|
||||||
page */
|
page */
|
||||||
mtr_t* mtr) /*!< in: mtr handle */
|
mtr_t* mtr, /*!< in/out: mini-transaction handle */
|
||||||
|
mtr_t* init_mtr)/*!< in/out: mtr or another mini-transaction
|
||||||
|
in which the page should be initialized.
|
||||||
|
If init_mtr!=mtr, but the page is already
|
||||||
|
latched in mtr, do not initialize the page. */
|
||||||
{
|
{
|
||||||
fseg_inode_t* inode;
|
fseg_inode_t* inode;
|
||||||
ulint space;
|
ulint space;
|
||||||
ulint flags;
|
ulint flags;
|
||||||
ulint zip_size;
|
ulint zip_size;
|
||||||
rw_lock_t* latch;
|
rw_lock_t* latch;
|
||||||
ibool success;
|
buf_block_t* block;
|
||||||
ulint page_no;
|
|
||||||
ulint n_reserved;
|
ulint n_reserved;
|
||||||
|
|
||||||
space = page_get_space_id(page_align(seg_header));
|
space = page_get_space_id(page_align(seg_header));
|
||||||
@ -2796,43 +2882,20 @@ fseg_alloc_free_page_general(
|
|||||||
|
|
||||||
inode = fseg_inode_get(seg_header, space, zip_size, mtr);
|
inode = fseg_inode_get(seg_header, space, zip_size, mtr);
|
||||||
|
|
||||||
if (!has_done_reservation) {
|
if (!has_done_reservation
|
||||||
success = fsp_reserve_free_extents(&n_reserved, space, 2,
|
&& !fsp_reserve_free_extents(&n_reserved, space, 2,
|
||||||
FSP_NORMAL, mtr);
|
FSP_NORMAL, mtr)) {
|
||||||
if (!success) {
|
return(NULL);
|
||||||
return(FIL_NULL);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
page_no = fseg_alloc_free_page_low(space, zip_size,
|
block = fseg_alloc_free_page_low(space, zip_size,
|
||||||
inode, hint, direction, mtr);
|
inode, hint, direction,
|
||||||
|
mtr, init_mtr);
|
||||||
if (!has_done_reservation) {
|
if (!has_done_reservation) {
|
||||||
fil_space_release_free_extents(space, n_reserved);
|
fil_space_release_free_extents(space, n_reserved);
|
||||||
}
|
}
|
||||||
|
|
||||||
return(page_no);
|
return(block);
|
||||||
}
|
|
||||||
|
|
||||||
/**********************************************************************//**
|
|
||||||
Allocates a single free page from a segment. This function implements
|
|
||||||
the intelligent allocation strategy which tries to minimize file space
|
|
||||||
fragmentation.
|
|
||||||
@return allocated page offset, FIL_NULL if no page could be allocated */
|
|
||||||
UNIV_INTERN
|
|
||||||
ulint
|
|
||||||
fseg_alloc_free_page(
|
|
||||||
/*=================*/
|
|
||||||
fseg_header_t* seg_header,/*!< in: segment header */
|
|
||||||
ulint hint, /*!< in: hint of which page would be desirable */
|
|
||||||
byte direction,/*!< in: if the new page is needed because
|
|
||||||
of an index page split, and records are
|
|
||||||
inserted there in order, into which
|
|
||||||
direction they go alphabetically: FSP_DOWN,
|
|
||||||
FSP_UP, FSP_NO_DIR */
|
|
||||||
mtr_t* mtr) /*!< in: mtr handle */
|
|
||||||
{
|
|
||||||
return(fseg_alloc_free_page_general(seg_header, hint, direction,
|
|
||||||
FALSE, mtr));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**********************************************************************//**
|
/**********************************************************************//**
|
||||||
@ -3344,6 +3407,8 @@ crash:
|
|||||||
descr + XDES_FLST_NODE, mtr);
|
descr + XDES_FLST_NODE, mtr);
|
||||||
fsp_free_extent(space, zip_size, page, mtr);
|
fsp_free_extent(space, zip_size, page, mtr);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
mtr->n_freed_pages++;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**********************************************************************//**
|
/**********************************************************************//**
|
||||||
|
@ -11,8 +11,8 @@ ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
|||||||
FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
|
FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
|
||||||
|
|
||||||
You should have received a copy of the GNU General Public License along with
|
You should have received a copy of the GNU General Public License along with
|
||||||
this program; if not, write to the Free Software Foundation, Inc., 59 Temple
|
this program; if not, write to the Free Software Foundation, Inc.,
|
||||||
Place, Suite 330, Boston, MA 02111-1307 USA
|
51 Franklin Street, Suite 500, Boston, MA 02110-1335 USA
|
||||||
|
|
||||||
*****************************************************************************/
|
*****************************************************************************/
|
||||||
|
|
||||||
@ -2180,14 +2180,14 @@ ibool
|
|||||||
ibuf_add_free_page(void)
|
ibuf_add_free_page(void)
|
||||||
/*====================*/
|
/*====================*/
|
||||||
{
|
{
|
||||||
mtr_t mtr;
|
mtr_t mtr;
|
||||||
page_t* header_page;
|
page_t* header_page;
|
||||||
ulint flags;
|
ulint flags;
|
||||||
ulint zip_size;
|
ulint zip_size;
|
||||||
ulint page_no;
|
buf_block_t* block;
|
||||||
page_t* page;
|
page_t* page;
|
||||||
page_t* root;
|
page_t* root;
|
||||||
page_t* bitmap_page;
|
page_t* bitmap_page;
|
||||||
|
|
||||||
mtr_start(&mtr);
|
mtr_start(&mtr);
|
||||||
|
|
||||||
@ -2208,29 +2208,24 @@ ibuf_add_free_page(void)
|
|||||||
of a deadlock. This is the reason why we created a special ibuf
|
of a deadlock. This is the reason why we created a special ibuf
|
||||||
header page apart from the ibuf tree. */
|
header page apart from the ibuf tree. */
|
||||||
|
|
||||||
page_no = fseg_alloc_free_page(
|
block = fseg_alloc_free_page(
|
||||||
header_page + IBUF_HEADER + IBUF_TREE_SEG_HEADER, 0, FSP_UP,
|
header_page + IBUF_HEADER + IBUF_TREE_SEG_HEADER, 0, FSP_UP,
|
||||||
&mtr);
|
&mtr);
|
||||||
|
|
||||||
if (UNIV_UNLIKELY(page_no == FIL_NULL)) {
|
if (block == NULL) {
|
||||||
mtr_commit(&mtr);
|
mtr_commit(&mtr);
|
||||||
|
|
||||||
return(FALSE);
|
return(FALSE);
|
||||||
} else {
|
|
||||||
buf_block_t* block = buf_page_get(
|
|
||||||
IBUF_SPACE_ID, 0, page_no, RW_X_LATCH, &mtr);
|
|
||||||
|
|
||||||
ibuf_enter(&mtr);
|
|
||||||
|
|
||||||
mutex_enter(&ibuf_mutex);
|
|
||||||
|
|
||||||
root = ibuf_tree_root_get(&mtr);
|
|
||||||
|
|
||||||
buf_block_dbg_add_level(block, SYNC_IBUF_TREE_NODE_NEW);
|
|
||||||
|
|
||||||
page = buf_block_get_frame(block);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ut_ad(rw_lock_get_x_lock_count(&block->lock) == 1);
|
||||||
|
ibuf_enter(&mtr);
|
||||||
|
mutex_enter(&ibuf_mutex);
|
||||||
|
root = ibuf_tree_root_get(&mtr);
|
||||||
|
|
||||||
|
buf_block_dbg_add_level(block, SYNC_IBUF_TREE_NODE_NEW);
|
||||||
|
page = buf_block_get_frame(block);
|
||||||
|
|
||||||
/* Add the page to the free list and update the ibuf size data */
|
/* Add the page to the free list and update the ibuf size data */
|
||||||
|
|
||||||
flst_add_last(root + PAGE_HEADER + PAGE_BTR_IBUF_FREE_LIST,
|
flst_add_last(root + PAGE_HEADER + PAGE_BTR_IBUF_FREE_LIST,
|
||||||
@ -2246,12 +2241,13 @@ ibuf_add_free_page(void)
|
|||||||
(level 2 page) */
|
(level 2 page) */
|
||||||
|
|
||||||
bitmap_page = ibuf_bitmap_get_map_page(
|
bitmap_page = ibuf_bitmap_get_map_page(
|
||||||
IBUF_SPACE_ID, page_no, zip_size, &mtr);
|
IBUF_SPACE_ID, buf_block_get_page_no(block), zip_size, &mtr);
|
||||||
|
|
||||||
mutex_exit(&ibuf_mutex);
|
mutex_exit(&ibuf_mutex);
|
||||||
|
|
||||||
ibuf_bitmap_page_set_bits(
|
ibuf_bitmap_page_set_bits(
|
||||||
bitmap_page, page_no, zip_size, IBUF_BITMAP_IBUF, TRUE, &mtr);
|
bitmap_page, buf_block_get_page_no(block), zip_size,
|
||||||
|
IBUF_BITMAP_IBUF, TRUE, &mtr);
|
||||||
|
|
||||||
ibuf_mtr_commit(&mtr);
|
ibuf_mtr_commit(&mtr);
|
||||||
|
|
||||||
|
@ -11,8 +11,8 @@ ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
|||||||
FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
|
FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
|
||||||
|
|
||||||
You should have received a copy of the GNU General Public License along with
|
You should have received a copy of the GNU General Public License along with
|
||||||
this program; if not, write to the Free Software Foundation, Inc., 59 Temple
|
this program; if not, write to the Free Software Foundation, Inc.,
|
||||||
Place, Suite 330, Boston, MA 02111-1307 USA
|
51 Franklin Street, Suite 500, Boston, MA 02110-1335 USA
|
||||||
|
|
||||||
*****************************************************************************/
|
*****************************************************************************/
|
||||||
|
|
||||||
@ -519,11 +519,14 @@ UNIV_INTERN
|
|||||||
ibool
|
ibool
|
||||||
btr_compress(
|
btr_compress(
|
||||||
/*=========*/
|
/*=========*/
|
||||||
btr_cur_t* cursor, /*!< in: cursor on the page to merge or lift;
|
btr_cur_t* cursor, /*!< in/out: cursor on the page to merge
|
||||||
the page must not be empty: in record delete
|
or lift; the page must not be empty:
|
||||||
use btr_discard_page if the page would become
|
when deleting records, use btr_discard_page()
|
||||||
empty */
|
if the page would become empty */
|
||||||
mtr_t* mtr); /*!< in: mtr */
|
ibool adjust, /*!< in: TRUE if should adjust the
|
||||||
|
cursor position even if compression occurs */
|
||||||
|
mtr_t* mtr) /*!< in/out: mini-transaction */
|
||||||
|
__attribute__((nonnull));
|
||||||
/*************************************************************//**
|
/*************************************************************//**
|
||||||
Discards a page from a B-tree. This is used to remove the last record from
|
Discards a page from a B-tree. This is used to remove the last record from
|
||||||
a B-tree page: the whole page must be removed at the same time. This cannot
|
a B-tree page: the whole page must be removed at the same time. This cannot
|
||||||
@ -574,7 +577,10 @@ btr_get_size(
|
|||||||
/**************************************************************//**
|
/**************************************************************//**
|
||||||
Allocates a new file page to be used in an index tree. NOTE: we assume
|
Allocates a new file page to be used in an index tree. NOTE: we assume
|
||||||
that the caller has made the reservation for free extents!
|
that the caller has made the reservation for free extents!
|
||||||
@return new allocated block, x-latched; NULL if out of space */
|
@retval NULL if no page could be allocated
|
||||||
|
@retval block, rw_lock_x_lock_count(&block->lock) == 1 if allocation succeeded
|
||||||
|
(init_mtr == mtr, or the page was not previously freed in mtr)
|
||||||
|
@retval block (not allocated or initialized) otherwise */
|
||||||
UNIV_INTERN
|
UNIV_INTERN
|
||||||
buf_block_t*
|
buf_block_t*
|
||||||
btr_page_alloc(
|
btr_page_alloc(
|
||||||
@ -585,7 +591,12 @@ btr_page_alloc(
|
|||||||
page split is made */
|
page split is made */
|
||||||
ulint level, /*!< in: level where the page is placed
|
ulint level, /*!< in: level where the page is placed
|
||||||
in the tree */
|
in the tree */
|
||||||
mtr_t* mtr); /*!< in: mtr */
|
mtr_t* mtr, /*!< in/out: mini-transaction
|
||||||
|
for the allocation */
|
||||||
|
mtr_t* init_mtr) /*!< in/out: mini-transaction
|
||||||
|
for x-latching and initializing
|
||||||
|
the page */
|
||||||
|
__attribute__((nonnull, warn_unused_result));
|
||||||
/**************************************************************//**
|
/**************************************************************//**
|
||||||
Frees a file page used in an index tree. NOTE: cannot free field external
|
Frees a file page used in an index tree. NOTE: cannot free field external
|
||||||
storage pages because the page must contain info on its level. */
|
storage pages because the page must contain info on its level. */
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
/*****************************************************************************
|
/*****************************************************************************
|
||||||
|
|
||||||
Copyright (c) 1994, 2010, Innobase Oy. All Rights Reserved.
|
Copyright (c) 1994, 2012, Oracle and/or its affiliates. All Rights Reserved.
|
||||||
|
|
||||||
This program is free software; you can redistribute it and/or modify it under
|
This program is free software; you can redistribute it and/or modify it under
|
||||||
the terms of the GNU General Public License as published by the Free Software
|
the terms of the GNU General Public License as published by the Free Software
|
||||||
@ -11,8 +11,8 @@ ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
|||||||
FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
|
FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
|
||||||
|
|
||||||
You should have received a copy of the GNU General Public License along with
|
You should have received a copy of the GNU General Public License along with
|
||||||
this program; if not, write to the Free Software Foundation, Inc., 59 Temple
|
this program; if not, write to the Free Software Foundation, Inc.,
|
||||||
Place, Suite 330, Boston, MA 02111-1307 USA
|
51 Franklin Street, Suite 500, Boston, MA 02110-1335 USA
|
||||||
|
|
||||||
*****************************************************************************/
|
*****************************************************************************/
|
||||||
|
|
||||||
@ -36,6 +36,9 @@ Created 10/16/1994 Heikki Tuuri
|
|||||||
#define BTR_NO_LOCKING_FLAG 2 /* do no record lock checking */
|
#define BTR_NO_LOCKING_FLAG 2 /* do no record lock checking */
|
||||||
#define BTR_KEEP_SYS_FLAG 4 /* sys fields will be found from the
|
#define BTR_KEEP_SYS_FLAG 4 /* sys fields will be found from the
|
||||||
update vector or inserted entry */
|
update vector or inserted entry */
|
||||||
|
#define BTR_KEEP_POS_FLAG 8 /* btr_cur_pessimistic_update()
|
||||||
|
must keep cursor position when
|
||||||
|
moving columns to big_rec */
|
||||||
|
|
||||||
#ifndef UNIV_HOTBACKUP
|
#ifndef UNIV_HOTBACKUP
|
||||||
#include "que0types.h"
|
#include "que0types.h"
|
||||||
@ -310,7 +313,9 @@ btr_cur_pessimistic_update(
|
|||||||
/*=======================*/
|
/*=======================*/
|
||||||
ulint flags, /*!< in: undo logging, locking, and rollback
|
ulint flags, /*!< in: undo logging, locking, and rollback
|
||||||
flags */
|
flags */
|
||||||
btr_cur_t* cursor, /*!< in: cursor on the record to update */
|
btr_cur_t* cursor, /*!< in/out: cursor on the record to update;
|
||||||
|
cursor may become invalid if *big_rec == NULL
|
||||||
|
|| !(flags & BTR_KEEP_POS_FLAG) */
|
||||||
mem_heap_t** heap, /*!< in/out: pointer to memory heap, or NULL */
|
mem_heap_t** heap, /*!< in/out: pointer to memory heap, or NULL */
|
||||||
big_rec_t** big_rec,/*!< out: big rec vector whose fields have to
|
big_rec_t** big_rec,/*!< out: big rec vector whose fields have to
|
||||||
be stored externally by the caller, or NULL */
|
be stored externally by the caller, or NULL */
|
||||||
@ -364,10 +369,13 @@ UNIV_INTERN
|
|||||||
ibool
|
ibool
|
||||||
btr_cur_compress_if_useful(
|
btr_cur_compress_if_useful(
|
||||||
/*=======================*/
|
/*=======================*/
|
||||||
btr_cur_t* cursor, /*!< in: cursor on the page to compress;
|
btr_cur_t* cursor, /*!< in/out: cursor on the page to compress;
|
||||||
cursor does not stay valid if compression
|
cursor does not stay valid if compression
|
||||||
occurs */
|
occurs */
|
||||||
mtr_t* mtr); /*!< in: mtr */
|
ibool adjust, /*!< in: TRUE if should adjust the
|
||||||
|
cursor position even if compression occurs */
|
||||||
|
mtr_t* mtr) /*!< in/out: mini-transaction */
|
||||||
|
__attribute__((nonnull));
|
||||||
/*******************************************************//**
|
/*******************************************************//**
|
||||||
Removes the record on which the tree cursor is positioned. It is assumed
|
Removes the record on which the tree cursor is positioned. It is assumed
|
||||||
that the mtr has an x-latch on the page where the cursor is positioned,
|
that the mtr has an x-latch on the page where the cursor is positioned,
|
||||||
@ -492,6 +500,27 @@ btr_cur_disown_inherited_fields(
|
|||||||
const upd_t* update, /*!< in: update vector */
|
const upd_t* update, /*!< in: update vector */
|
||||||
mtr_t* mtr) /*!< in/out: mini-transaction */
|
mtr_t* mtr) /*!< in/out: mini-transaction */
|
||||||
__attribute__((nonnull(2,3,4,5,6)));
|
__attribute__((nonnull(2,3,4,5,6)));
|
||||||
|
|
||||||
|
/** Operation code for btr_store_big_rec_extern_fields(). */
|
||||||
|
enum blob_op {
|
||||||
|
/** Store off-page columns for a freshly inserted record */
|
||||||
|
BTR_STORE_INSERT = 0,
|
||||||
|
/** Store off-page columns for an insert by update */
|
||||||
|
BTR_STORE_INSERT_UPDATE,
|
||||||
|
/** Store off-page columns for an update */
|
||||||
|
BTR_STORE_UPDATE
|
||||||
|
};
|
||||||
|
|
||||||
|
/*******************************************************************//**
|
||||||
|
Determine if an operation on off-page columns is an update.
|
||||||
|
@return TRUE if op != BTR_STORE_INSERT */
|
||||||
|
UNIV_INLINE
|
||||||
|
ibool
|
||||||
|
btr_blob_op_is_update(
|
||||||
|
/*==================*/
|
||||||
|
enum blob_op op) /*!< in: operation */
|
||||||
|
__attribute__((warn_unused_result));
|
||||||
|
|
||||||
/*******************************************************************//**
|
/*******************************************************************//**
|
||||||
Stores the fields in big_rec_vec to the tablespace and puts pointers to
|
Stores the fields in big_rec_vec to the tablespace and puts pointers to
|
||||||
them in rec. The extern flags in rec will have to be set beforehand.
|
them in rec. The extern flags in rec will have to be set beforehand.
|
||||||
@ -499,52 +528,23 @@ The fields are stored on pages allocated from leaf node
|
|||||||
file segment of the index tree.
|
file segment of the index tree.
|
||||||
@return DB_SUCCESS or DB_OUT_OF_FILE_SPACE */
|
@return DB_SUCCESS or DB_OUT_OF_FILE_SPACE */
|
||||||
UNIV_INTERN
|
UNIV_INTERN
|
||||||
ulint
|
enum db_err
|
||||||
btr_store_big_rec_extern_fields_func(
|
btr_store_big_rec_extern_fields(
|
||||||
/*=================================*/
|
/*============================*/
|
||||||
dict_index_t* index, /*!< in: index of rec; the index tree
|
dict_index_t* index, /*!< in: index of rec; the index tree
|
||||||
MUST be X-latched */
|
MUST be X-latched */
|
||||||
buf_block_t* rec_block, /*!< in/out: block containing rec */
|
buf_block_t* rec_block, /*!< in/out: block containing rec */
|
||||||
rec_t* rec, /*!< in: record */
|
rec_t* rec, /*!< in/out: record */
|
||||||
const ulint* offsets, /*!< in: rec_get_offsets(rec, index);
|
const ulint* offsets, /*!< in: rec_get_offsets(rec, index);
|
||||||
the "external storage" flags in offsets
|
the "external storage" flags in offsets
|
||||||
will not correspond to rec when
|
will not correspond to rec when
|
||||||
this function returns */
|
this function returns */
|
||||||
#ifdef UNIV_DEBUG
|
const big_rec_t*big_rec_vec, /*!< in: vector containing fields
|
||||||
mtr_t* local_mtr, /*!< in: mtr containing the
|
|
||||||
latch to rec and to the tree */
|
|
||||||
#endif /* UNIV_DEBUG */
|
|
||||||
#if defined UNIV_DEBUG || defined UNIV_BLOB_LIGHT_DEBUG
|
|
||||||
ibool update_in_place,/*! in: TRUE if the record is updated
|
|
||||||
in place (not delete+insert) */
|
|
||||||
#endif /* UNIV_DEBUG || UNIV_BLOB_LIGHT_DEBUG */
|
|
||||||
const big_rec_t*big_rec_vec) /*!< in: vector containing fields
|
|
||||||
to be stored externally */
|
to be stored externally */
|
||||||
__attribute__((nonnull));
|
mtr_t* btr_mtr, /*!< in: mtr containing the
|
||||||
|
latches to the clustered index */
|
||||||
/** Stores the fields in big_rec_vec to the tablespace and puts pointers to
|
enum blob_op op) /*! in: operation code */
|
||||||
them in rec. The extern flags in rec will have to be set beforehand.
|
__attribute__((nonnull, warn_unused_result));
|
||||||
The fields are stored on pages allocated from leaf node
|
|
||||||
file segment of the index tree.
|
|
||||||
@param index in: clustered index; MUST be X-latched by mtr
|
|
||||||
@param b in/out: block containing rec; MUST be X-latched by mtr
|
|
||||||
@param rec in/out: clustered index record
|
|
||||||
@param offsets in: rec_get_offsets(rec, index);
|
|
||||||
the "external storage" flags in offsets will not be adjusted
|
|
||||||
@param mtr in: mini-transaction that holds x-latch on index and b
|
|
||||||
@param upd in: TRUE if the record is updated in place (not delete+insert)
|
|
||||||
@param big in: vector containing fields to be stored externally
|
|
||||||
@return DB_SUCCESS or DB_OUT_OF_FILE_SPACE */
|
|
||||||
#ifdef UNIV_DEBUG
|
|
||||||
# define btr_store_big_rec_extern_fields(index,b,rec,offsets,mtr,upd,big) \
|
|
||||||
btr_store_big_rec_extern_fields_func(index,b,rec,offsets,mtr,upd,big)
|
|
||||||
#elif defined UNIV_BLOB_LIGHT_DEBUG
|
|
||||||
# define btr_store_big_rec_extern_fields(index,b,rec,offsets,mtr,upd,big) \
|
|
||||||
btr_store_big_rec_extern_fields_func(index,b,rec,offsets,upd,big)
|
|
||||||
#else
|
|
||||||
# define btr_store_big_rec_extern_fields(index,b,rec,offsets,mtr,upd,big) \
|
|
||||||
btr_store_big_rec_extern_fields_func(index,b,rec,offsets,big)
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/*******************************************************************//**
|
/*******************************************************************//**
|
||||||
Frees the space in an externally stored field to the file space
|
Frees the space in an externally stored field to the file space
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
/*****************************************************************************
|
/*****************************************************************************
|
||||||
|
|
||||||
Copyright (c) 1994, 2009, Innobase Oy. All Rights Reserved.
|
Copyright (c) 1994, 2012, Oracle and/or its affiliates. All Rights Reserved.
|
||||||
|
|
||||||
This program is free software; you can redistribute it and/or modify it under
|
This program is free software; you can redistribute it and/or modify it under
|
||||||
the terms of the GNU General Public License as published by the Free Software
|
the terms of the GNU General Public License as published by the Free Software
|
||||||
@ -11,8 +11,8 @@ ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
|||||||
FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
|
FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
|
||||||
|
|
||||||
You should have received a copy of the GNU General Public License along with
|
You should have received a copy of the GNU General Public License along with
|
||||||
this program; if not, write to the Free Software Foundation, Inc., 59 Temple
|
this program; if not, write to the Free Software Foundation, Inc.,
|
||||||
Place, Suite 330, Boston, MA 02111-1307 USA
|
51 Franklin Street, Suite 500, Boston, MA 02110-1335 USA
|
||||||
|
|
||||||
*****************************************************************************/
|
*****************************************************************************/
|
||||||
|
|
||||||
@ -139,7 +139,7 @@ btr_cur_compress_recommendation(
|
|||||||
btr_cur_t* cursor, /*!< in: btr cursor */
|
btr_cur_t* cursor, /*!< in: btr cursor */
|
||||||
mtr_t* mtr) /*!< in: mtr */
|
mtr_t* mtr) /*!< in: mtr */
|
||||||
{
|
{
|
||||||
page_t* page;
|
const page_t* page;
|
||||||
|
|
||||||
ut_ad(mtr_memo_contains(mtr, btr_cur_get_block(cursor),
|
ut_ad(mtr_memo_contains(mtr, btr_cur_get_block(cursor),
|
||||||
MTR_MEMO_PAGE_X_FIX));
|
MTR_MEMO_PAGE_X_FIX));
|
||||||
@ -197,4 +197,25 @@ btr_cur_can_delete_without_compress(
|
|||||||
|
|
||||||
return(TRUE);
|
return(TRUE);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*******************************************************************//**
|
||||||
|
Determine if an operation on off-page columns is an update.
|
||||||
|
@return TRUE if op != BTR_STORE_INSERT */
|
||||||
|
UNIV_INLINE
|
||||||
|
ibool
|
||||||
|
btr_blob_op_is_update(
|
||||||
|
/*==================*/
|
||||||
|
enum blob_op op) /*!< in: operation */
|
||||||
|
{
|
||||||
|
switch (op) {
|
||||||
|
case BTR_STORE_INSERT:
|
||||||
|
return(FALSE);
|
||||||
|
case BTR_STORE_INSERT_UPDATE:
|
||||||
|
case BTR_STORE_UPDATE:
|
||||||
|
return(TRUE);
|
||||||
|
}
|
||||||
|
|
||||||
|
ut_ad(0);
|
||||||
|
return(FALSE);
|
||||||
|
}
|
||||||
#endif /* !UNIV_HOTBACKUP */
|
#endif /* !UNIV_HOTBACKUP */
|
||||||
|
@ -11,8 +11,8 @@ ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
|||||||
FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
|
FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
|
||||||
|
|
||||||
You should have received a copy of the GNU General Public License along with
|
You should have received a copy of the GNU General Public License along with
|
||||||
this program; if not, write to the Free Software Foundation, Inc., 59 Temple
|
this program; if not, write to the Free Software Foundation, Inc.,
|
||||||
Place, Suite 330, Boston, MA 02111-1307 USA
|
51 Franklin Street, Suite 500, Boston, MA 02110-1335 USA
|
||||||
|
|
||||||
*****************************************************************************/
|
*****************************************************************************/
|
||||||
|
|
||||||
@ -596,6 +596,31 @@ buf_block_get_modify_clock(
|
|||||||
#else /* !UNIV_HOTBACKUP */
|
#else /* !UNIV_HOTBACKUP */
|
||||||
# define buf_block_modify_clock_inc(block) ((void) 0)
|
# define buf_block_modify_clock_inc(block) ((void) 0)
|
||||||
#endif /* !UNIV_HOTBACKUP */
|
#endif /* !UNIV_HOTBACKUP */
|
||||||
|
/*******************************************************************//**
|
||||||
|
Increments the bufferfix count. */
|
||||||
|
UNIV_INLINE
|
||||||
|
void
|
||||||
|
buf_block_buf_fix_inc_func(
|
||||||
|
/*=======================*/
|
||||||
|
#ifdef UNIV_SYNC_DEBUG
|
||||||
|
const char* file, /*!< in: file name */
|
||||||
|
ulint line, /*!< in: line */
|
||||||
|
#endif /* UNIV_SYNC_DEBUG */
|
||||||
|
buf_block_t* block) /*!< in/out: block to bufferfix */
|
||||||
|
__attribute__((nonnull));
|
||||||
|
#ifdef UNIV_SYNC_DEBUG
|
||||||
|
/** Increments the bufferfix count.
|
||||||
|
@param b in/out: block to bufferfix
|
||||||
|
@param f in: file name where requested
|
||||||
|
@param l in: line number where requested */
|
||||||
|
# define buf_block_buf_fix_inc(b,f,l) buf_block_buf_fix_inc_func(f,l,b)
|
||||||
|
#else /* UNIV_SYNC_DEBUG */
|
||||||
|
/** Increments the bufferfix count.
|
||||||
|
@param b in/out: block to bufferfix
|
||||||
|
@param f in: file name where requested
|
||||||
|
@param l in: line number where requested */
|
||||||
|
# define buf_block_buf_fix_inc(b,f,l) buf_block_buf_fix_inc_func(b)
|
||||||
|
#endif /* UNIV_SYNC_DEBUG */
|
||||||
/********************************************************************//**
|
/********************************************************************//**
|
||||||
Calculates a page checksum which is stored to the page when it is written
|
Calculates a page checksum which is stored to the page when it is written
|
||||||
to a file. Note that we must be careful to calculate the same value
|
to a file. Note that we must be careful to calculate the same value
|
||||||
|
@ -988,19 +988,6 @@ buf_block_buf_fix_inc_func(
|
|||||||
|
|
||||||
block->page.buf_fix_count++;
|
block->page.buf_fix_count++;
|
||||||
}
|
}
|
||||||
#ifdef UNIV_SYNC_DEBUG
|
|
||||||
/** Increments the bufferfix count.
|
|
||||||
@param b in/out: block to bufferfix
|
|
||||||
@param f in: file name where requested
|
|
||||||
@param l in: line number where requested */
|
|
||||||
# define buf_block_buf_fix_inc(b,f,l) buf_block_buf_fix_inc_func(f,l,b)
|
|
||||||
#else /* UNIV_SYNC_DEBUG */
|
|
||||||
/** Increments the bufferfix count.
|
|
||||||
@param b in/out: block to bufferfix
|
|
||||||
@param f in: file name where requested
|
|
||||||
@param l in: line number where requested */
|
|
||||||
# define buf_block_buf_fix_inc(b,f,l) buf_block_buf_fix_inc_func(b)
|
|
||||||
#endif /* UNIV_SYNC_DEBUG */
|
|
||||||
|
|
||||||
/*******************************************************************//**
|
/*******************************************************************//**
|
||||||
Decrements the bufferfix count. */
|
Decrements the bufferfix count. */
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
/*****************************************************************************
|
/*****************************************************************************
|
||||||
|
|
||||||
Copyright (c) 1995, 2011, Oracle and/or its affiliates. All Rights Reserved.
|
Copyright (c) 1995, 2012, Oracle and/or its affiliates. All Rights Reserved.
|
||||||
|
|
||||||
This program is free software; you can redistribute it and/or modify it under
|
This program is free software; you can redistribute it and/or modify it under
|
||||||
the terms of the GNU General Public License as published by the Free Software
|
the terms of the GNU General Public License as published by the Free Software
|
||||||
@ -260,30 +260,33 @@ fseg_n_reserved_pages(
|
|||||||
Allocates a single free page from a segment. This function implements
|
Allocates a single free page from a segment. This function implements
|
||||||
the intelligent allocation strategy which tries to minimize
|
the intelligent allocation strategy which tries to minimize
|
||||||
file space fragmentation.
|
file space fragmentation.
|
||||||
@return the allocated page offset FIL_NULL if no page could be allocated */
|
@param[in/out] seg_header segment header
|
||||||
UNIV_INTERN
|
@param[in] hint hint of which page would be desirable
|
||||||
ulint
|
@param[in] direction if the new page is needed because
|
||||||
fseg_alloc_free_page(
|
|
||||||
/*=================*/
|
|
||||||
fseg_header_t* seg_header, /*!< in: segment header */
|
|
||||||
ulint hint, /*!< in: hint of which page would be desirable */
|
|
||||||
byte direction, /*!< in: if the new page is needed because
|
|
||||||
of an index page split, and records are
|
of an index page split, and records are
|
||||||
inserted there in order, into which
|
inserted there in order, into which
|
||||||
direction they go alphabetically: FSP_DOWN,
|
direction they go alphabetically: FSP_DOWN,
|
||||||
FSP_UP, FSP_NO_DIR */
|
FSP_UP, FSP_NO_DIR
|
||||||
mtr_t* mtr); /*!< in: mtr handle */
|
@param[in/out] mtr mini-transaction
|
||||||
|
@return X-latched block, or NULL if no page could be allocated */
|
||||||
|
#define fseg_alloc_free_page(seg_header, hint, direction, mtr) \
|
||||||
|
fseg_alloc_free_page_general(seg_header, hint, direction, \
|
||||||
|
FALSE, mtr, mtr)
|
||||||
/**********************************************************************//**
|
/**********************************************************************//**
|
||||||
Allocates a single free page from a segment. This function implements
|
Allocates a single free page from a segment. This function implements
|
||||||
the intelligent allocation strategy which tries to minimize file space
|
the intelligent allocation strategy which tries to minimize file space
|
||||||
fragmentation.
|
fragmentation.
|
||||||
@return allocated page offset, FIL_NULL if no page could be allocated */
|
@retval NULL if no page could be allocated
|
||||||
|
@retval block, rw_lock_x_lock_count(&block->lock) == 1 if allocation succeeded
|
||||||
|
(init_mtr == mtr, or the page was not previously freed in mtr)
|
||||||
|
@retval block (not allocated or initialized) otherwise */
|
||||||
UNIV_INTERN
|
UNIV_INTERN
|
||||||
ulint
|
buf_block_t*
|
||||||
fseg_alloc_free_page_general(
|
fseg_alloc_free_page_general(
|
||||||
/*=========================*/
|
/*=========================*/
|
||||||
fseg_header_t* seg_header,/*!< in: segment header */
|
fseg_header_t* seg_header,/*!< in/out: segment header */
|
||||||
ulint hint, /*!< in: hint of which page would be desirable */
|
ulint hint, /*!< in: hint of which page would be
|
||||||
|
desirable */
|
||||||
byte direction,/*!< in: if the new page is needed because
|
byte direction,/*!< in: if the new page is needed because
|
||||||
of an index page split, and records are
|
of an index page split, and records are
|
||||||
inserted there in order, into which
|
inserted there in order, into which
|
||||||
@ -294,7 +297,12 @@ fseg_alloc_free_page_general(
|
|||||||
with fsp_reserve_free_extents, then there
|
with fsp_reserve_free_extents, then there
|
||||||
is no need to do the check for this individual
|
is no need to do the check for this individual
|
||||||
page */
|
page */
|
||||||
mtr_t* mtr); /*!< in: mtr handle */
|
mtr_t* mtr, /*!< in/out: mini-transaction */
|
||||||
|
mtr_t* init_mtr)/*!< in/out: mtr or another mini-transaction
|
||||||
|
in which the page should be initialized.
|
||||||
|
If init_mtr!=mtr, but the page is already
|
||||||
|
latched in mtr, do not initialize the page. */
|
||||||
|
__attribute__((warn_unused_result, nonnull));
|
||||||
/**********************************************************************//**
|
/**********************************************************************//**
|
||||||
Reserves free pages from a tablespace. All mini-transactions which may
|
Reserves free pages from a tablespace. All mini-transactions which may
|
||||||
use several pages from the tablespace should call this function beforehand
|
use several pages from the tablespace should call this function beforehand
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
/*****************************************************************************
|
/*****************************************************************************
|
||||||
|
|
||||||
Copyright (c) 1995, 2009, Innobase Oy. All Rights Reserved.
|
Copyright (c) 1995, 2012, Oracle and/or its affiliates. All Rights Reserved.
|
||||||
|
|
||||||
This program is free software; you can redistribute it and/or modify it under
|
This program is free software; you can redistribute it and/or modify it under
|
||||||
the terms of the GNU General Public License as published by the Free Software
|
the terms of the GNU General Public License as published by the Free Software
|
||||||
@ -50,7 +50,9 @@ first 3 values must be RW_S_LATCH, RW_X_LATCH, RW_NO_LATCH */
|
|||||||
#define MTR_MEMO_PAGE_S_FIX RW_S_LATCH
|
#define MTR_MEMO_PAGE_S_FIX RW_S_LATCH
|
||||||
#define MTR_MEMO_PAGE_X_FIX RW_X_LATCH
|
#define MTR_MEMO_PAGE_X_FIX RW_X_LATCH
|
||||||
#define MTR_MEMO_BUF_FIX RW_NO_LATCH
|
#define MTR_MEMO_BUF_FIX RW_NO_LATCH
|
||||||
#define MTR_MEMO_MODIFY 54
|
#ifdef UNIV_DEBUG
|
||||||
|
# define MTR_MEMO_MODIFY 54
|
||||||
|
#endif /* UNIV_DEBUG */
|
||||||
#define MTR_MEMO_S_LOCK 55
|
#define MTR_MEMO_S_LOCK 55
|
||||||
#define MTR_MEMO_X_LOCK 56
|
#define MTR_MEMO_X_LOCK 56
|
||||||
|
|
||||||
@ -376,6 +378,9 @@ struct mtr_struct{
|
|||||||
ulint n_log_recs;
|
ulint n_log_recs;
|
||||||
/* count of how many page initial log records
|
/* count of how many page initial log records
|
||||||
have been written to the mtr log */
|
have been written to the mtr log */
|
||||||
|
ulint n_freed_pages;
|
||||||
|
/* number of pages that have been freed in
|
||||||
|
this mini-transaction */
|
||||||
ulint log_mode; /* specifies which operations should be
|
ulint log_mode; /* specifies which operations should be
|
||||||
logged; default value MTR_LOG_ALL */
|
logged; default value MTR_LOG_ALL */
|
||||||
ib_uint64_t start_lsn;/* start lsn of the possible log entry for
|
ib_uint64_t start_lsn;/* start lsn of the possible log entry for
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
/*****************************************************************************
|
/*****************************************************************************
|
||||||
|
|
||||||
Copyright (c) 1995, 2010, Innobase Oy. All Rights Reserved.
|
Copyright (c) 1995, 2012, Oracle and/or its affiliates. All Rights Reserved.
|
||||||
|
|
||||||
This program is free software; you can redistribute it and/or modify it under
|
This program is free software; you can redistribute it and/or modify it under
|
||||||
the terms of the GNU General Public License as published by the Free Software
|
the terms of the GNU General Public License as published by the Free Software
|
||||||
@ -11,8 +11,8 @@ ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
|||||||
FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
|
FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
|
||||||
|
|
||||||
You should have received a copy of the GNU General Public License along with
|
You should have received a copy of the GNU General Public License along with
|
||||||
this program; if not, write to the Free Software Foundation, Inc., 59 Temple
|
this program; if not, write to the Free Software Foundation, Inc.,
|
||||||
Place, Suite 330, Boston, MA 02111-1307 USA
|
51 Franklin Street, Suite 500, Boston, MA 02110-1335 USA
|
||||||
|
|
||||||
*****************************************************************************/
|
*****************************************************************************/
|
||||||
|
|
||||||
@ -46,6 +46,7 @@ mtr_start(
|
|||||||
mtr->modifications = FALSE;
|
mtr->modifications = FALSE;
|
||||||
mtr->inside_ibuf = FALSE;
|
mtr->inside_ibuf = FALSE;
|
||||||
mtr->n_log_recs = 0;
|
mtr->n_log_recs = 0;
|
||||||
|
mtr->n_freed_pages = 0;
|
||||||
|
|
||||||
ut_d(mtr->state = MTR_ACTIVE);
|
ut_d(mtr->state = MTR_ACTIVE);
|
||||||
ut_d(mtr->magic_n = MTR_MAGIC_N);
|
ut_d(mtr->magic_n = MTR_MAGIC_N);
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
/*****************************************************************************
|
/*****************************************************************************
|
||||||
|
|
||||||
Copyright (c) 1994, 2009, Innobase Oy. All Rights Reserved.
|
Copyright (c) 1994, 2012, Oracle and/or its affiliates. All Rights Reserved.
|
||||||
|
|
||||||
This program is free software; you can redistribute it and/or modify it under
|
This program is free software; you can redistribute it and/or modify it under
|
||||||
the terms of the GNU General Public License as published by the Free Software
|
the terms of the GNU General Public License as published by the Free Software
|
||||||
@ -11,8 +11,8 @@ ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
|||||||
FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
|
FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
|
||||||
|
|
||||||
You should have received a copy of the GNU General Public License along with
|
You should have received a copy of the GNU General Public License along with
|
||||||
this program; if not, write to the Free Software Foundation, Inc., 59 Temple
|
this program; if not, write to the Free Software Foundation, Inc.,
|
||||||
Place, Suite 330, Boston, MA 02111-1307 USA
|
51 Franklin Street, Suite 500, Boston, MA 02110-1335 USA
|
||||||
|
|
||||||
*****************************************************************************/
|
*****************************************************************************/
|
||||||
|
|
||||||
@ -281,16 +281,42 @@ page_get_supremum_offset(
|
|||||||
const page_t* page); /*!< in: page which must have record(s) */
|
const page_t* page); /*!< in: page which must have record(s) */
|
||||||
#define page_get_infimum_rec(page) ((page) + page_get_infimum_offset(page))
|
#define page_get_infimum_rec(page) ((page) + page_get_infimum_offset(page))
|
||||||
#define page_get_supremum_rec(page) ((page) + page_get_supremum_offset(page))
|
#define page_get_supremum_rec(page) ((page) + page_get_supremum_offset(page))
|
||||||
|
|
||||||
/************************************************************//**
|
/************************************************************//**
|
||||||
Returns the middle record of record list. If there are an even number
|
Returns the nth record of the record list.
|
||||||
of records in the list, returns the first record of upper half-list.
|
This is the inverse function of page_rec_get_n_recs_before().
|
||||||
@return middle record */
|
@return nth record */
|
||||||
UNIV_INTERN
|
UNIV_INTERN
|
||||||
|
const rec_t*
|
||||||
|
page_rec_get_nth_const(
|
||||||
|
/*===================*/
|
||||||
|
const page_t* page, /*!< in: page */
|
||||||
|
ulint nth) /*!< in: nth record */
|
||||||
|
__attribute__((nonnull, warn_unused_result));
|
||||||
|
/************************************************************//**
|
||||||
|
Returns the nth record of the record list.
|
||||||
|
This is the inverse function of page_rec_get_n_recs_before().
|
||||||
|
@return nth record */
|
||||||
|
UNIV_INLINE
|
||||||
|
rec_t*
|
||||||
|
page_rec_get_nth(
|
||||||
|
/*=============*/
|
||||||
|
page_t* page, /*< in: page */
|
||||||
|
ulint nth) /*!< in: nth record */
|
||||||
|
__attribute__((nonnull, warn_unused_result));
|
||||||
|
|
||||||
|
#ifndef UNIV_HOTBACKUP
|
||||||
|
/************************************************************//**
|
||||||
|
Returns the middle record of the records on the page. If there is an
|
||||||
|
even number of records in the list, returns the first record of the
|
||||||
|
upper half-list.
|
||||||
|
@return middle record */
|
||||||
|
UNIV_INLINE
|
||||||
rec_t*
|
rec_t*
|
||||||
page_get_middle_rec(
|
page_get_middle_rec(
|
||||||
/*================*/
|
/*================*/
|
||||||
page_t* page); /*!< in: page */
|
page_t* page) /*!< in: page */
|
||||||
#ifndef UNIV_HOTBACKUP
|
__attribute__((nonnull, warn_unused_result));
|
||||||
/*************************************************************//**
|
/*************************************************************//**
|
||||||
Compares a data tuple to a physical record. Differs from the function
|
Compares a data tuple to a physical record. Differs from the function
|
||||||
cmp_dtuple_rec_with_match in the way that the record must reside on an
|
cmp_dtuple_rec_with_match in the way that the record must reside on an
|
||||||
@ -345,6 +371,7 @@ page_get_n_recs(
|
|||||||
/***************************************************************//**
|
/***************************************************************//**
|
||||||
Returns the number of records before the given record in chain.
|
Returns the number of records before the given record in chain.
|
||||||
The number includes infimum and supremum records.
|
The number includes infimum and supremum records.
|
||||||
|
This is the inverse function of page_rec_get_nth().
|
||||||
@return number of records */
|
@return number of records */
|
||||||
UNIV_INTERN
|
UNIV_INTERN
|
||||||
ulint
|
ulint
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
/*****************************************************************************
|
/*****************************************************************************
|
||||||
|
|
||||||
Copyright (c) 1994, 2009, Innobase Oy. All Rights Reserved.
|
Copyright (c) 1994, 2012, Oracle and/or its affiliates. All Rights Reserved.
|
||||||
|
|
||||||
This program is free software; you can redistribute it and/or modify it under
|
This program is free software; you can redistribute it and/or modify it under
|
||||||
the terms of the GNU General Public License as published by the Free Software
|
the terms of the GNU General Public License as published by the Free Software
|
||||||
@ -11,8 +11,8 @@ ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
|||||||
FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
|
FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
|
||||||
|
|
||||||
You should have received a copy of the GNU General Public License along with
|
You should have received a copy of the GNU General Public License along with
|
||||||
this program; if not, write to the Free Software Foundation, Inc., 59 Temple
|
this program; if not, write to the Free Software Foundation, Inc.,
|
||||||
Place, Suite 330, Boston, MA 02111-1307 USA
|
51 Franklin Street, Suite 500, Boston, MA 02110-1335 USA
|
||||||
|
|
||||||
*****************************************************************************/
|
*****************************************************************************/
|
||||||
|
|
||||||
@ -419,7 +419,37 @@ page_rec_is_infimum(
|
|||||||
return(page_rec_is_infimum_low(page_offset(rec)));
|
return(page_rec_is_infimum_low(page_offset(rec)));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/************************************************************//**
|
||||||
|
Returns the nth record of the record list.
|
||||||
|
This is the inverse function of page_rec_get_n_recs_before().
|
||||||
|
@return nth record */
|
||||||
|
UNIV_INLINE
|
||||||
|
rec_t*
|
||||||
|
page_rec_get_nth(
|
||||||
|
/*=============*/
|
||||||
|
page_t* page, /*!< in: page */
|
||||||
|
ulint nth) /*!< in: nth record */
|
||||||
|
{
|
||||||
|
return((rec_t*) page_rec_get_nth_const(page, nth));
|
||||||
|
}
|
||||||
|
|
||||||
#ifndef UNIV_HOTBACKUP
|
#ifndef UNIV_HOTBACKUP
|
||||||
|
/************************************************************//**
|
||||||
|
Returns the middle record of the records on the page. If there is an
|
||||||
|
even number of records in the list, returns the first record of the
|
||||||
|
upper half-list.
|
||||||
|
@return middle record */
|
||||||
|
UNIV_INLINE
|
||||||
|
rec_t*
|
||||||
|
page_get_middle_rec(
|
||||||
|
/*================*/
|
||||||
|
page_t* page) /*!< in: page */
|
||||||
|
{
|
||||||
|
ulint middle = (page_get_n_recs(page) + PAGE_HEAP_NO_USER_LOW) / 2;
|
||||||
|
|
||||||
|
return(page_rec_get_nth(page, middle));
|
||||||
|
}
|
||||||
|
|
||||||
/*************************************************************//**
|
/*************************************************************//**
|
||||||
Compares a data tuple to a physical record. Differs from the function
|
Compares a data tuple to a physical record. Differs from the function
|
||||||
cmp_dtuple_rec_with_match in the way that the record must reside on an
|
cmp_dtuple_rec_with_match in the way that the record must reside on an
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
/*****************************************************************************
|
/*****************************************************************************
|
||||||
|
|
||||||
Copyright (c) 1996, 2009, Innobase Oy. All Rights Reserved.
|
Copyright (c) 1996, 2012, Oracle and/or its affiliates. All Rights Reserved.
|
||||||
|
|
||||||
This program is free software; you can redistribute it and/or modify it under
|
This program is free software; you can redistribute it and/or modify it under
|
||||||
the terms of the GNU General Public License as published by the Free Software
|
the terms of the GNU General Public License as published by the Free Software
|
||||||
@ -11,8 +11,8 @@ ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
|||||||
FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
|
FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
|
||||||
|
|
||||||
You should have received a copy of the GNU General Public License along with
|
You should have received a copy of the GNU General Public License along with
|
||||||
this program; if not, write to the Free Software Foundation, Inc., 59 Temple
|
this program; if not, write to the Free Software Foundation, Inc.,
|
||||||
Place, Suite 330, Boston, MA 02111-1307 USA
|
51 Franklin Street, Suite 500, Boston, MA 02110-1335 USA
|
||||||
|
|
||||||
*****************************************************************************/
|
*****************************************************************************/
|
||||||
|
|
||||||
@ -107,6 +107,7 @@ trx_undo_rec_copy(
|
|||||||
|
|
||||||
len = mach_read_from_2(undo_rec)
|
len = mach_read_from_2(undo_rec)
|
||||||
- ut_align_offset(undo_rec, UNIV_PAGE_SIZE);
|
- ut_align_offset(undo_rec, UNIV_PAGE_SIZE);
|
||||||
|
ut_ad(len < UNIV_PAGE_SIZE);
|
||||||
return(mem_heap_dup(heap, undo_rec, len));
|
return(mem_heap_dup(heap, undo_rec, len));
|
||||||
}
|
}
|
||||||
#endif /* !UNIV_HOTBACKUP */
|
#endif /* !UNIV_HOTBACKUP */
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
/*****************************************************************************
|
/*****************************************************************************
|
||||||
|
|
||||||
Copyright (c) 1996, 2011, Oracle and/or its affiliates. All Rights Reserved.
|
Copyright (c) 1996, 2012, Oracle and/or its affiliates. All Rights Reserved.
|
||||||
|
|
||||||
This program is free software; you can redistribute it and/or modify it under
|
This program is free software; you can redistribute it and/or modify it under
|
||||||
the terms of the GNU General Public License as published by the Free Software
|
the terms of the GNU General Public License as published by the Free Software
|
||||||
@ -11,8 +11,8 @@ ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
|||||||
FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
|
FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
|
||||||
|
|
||||||
You should have received a copy of the GNU General Public License along with
|
You should have received a copy of the GNU General Public License along with
|
||||||
this program; if not, write to the Free Software Foundation, Inc., 59 Temple
|
this program; if not, write to the Free Software Foundation, Inc.,
|
||||||
Place, Suite 330, Boston, MA 02111-1307 USA
|
51 Franklin Street, Suite 500, Boston, MA 02110-1335 USA
|
||||||
|
|
||||||
*****************************************************************************/
|
*****************************************************************************/
|
||||||
|
|
||||||
@ -194,16 +194,17 @@ trx_undo_get_first_rec(
|
|||||||
mtr_t* mtr); /*!< in: mtr */
|
mtr_t* mtr); /*!< in: mtr */
|
||||||
/********************************************************************//**
|
/********************************************************************//**
|
||||||
Tries to add a page to the undo log segment where the undo log is placed.
|
Tries to add a page to the undo log segment where the undo log is placed.
|
||||||
@return page number if success, else FIL_NULL */
|
@return X-latched block if success, else NULL */
|
||||||
UNIV_INTERN
|
UNIV_INTERN
|
||||||
ulint
|
buf_block_t*
|
||||||
trx_undo_add_page(
|
trx_undo_add_page(
|
||||||
/*==============*/
|
/*==============*/
|
||||||
trx_t* trx, /*!< in: transaction */
|
trx_t* trx, /*!< in: transaction */
|
||||||
trx_undo_t* undo, /*!< in: undo log memory object */
|
trx_undo_t* undo, /*!< in: undo log memory object */
|
||||||
mtr_t* mtr); /*!< in: mtr which does not have a latch to any
|
mtr_t* mtr) /*!< in: mtr which does not have a latch to any
|
||||||
undo log page; the caller must have reserved
|
undo log page; the caller must have reserved
|
||||||
the rollback segment mutex */
|
the rollback segment mutex */
|
||||||
|
__attribute__((nonnull, warn_unused_result));
|
||||||
/********************************************************************//**
|
/********************************************************************//**
|
||||||
Frees the last undo log page.
|
Frees the last undo log page.
|
||||||
The caller must hold the rollback segment mutex. */
|
The caller must hold the rollback segment mutex. */
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
/*****************************************************************************
|
/*****************************************************************************
|
||||||
|
|
||||||
Copyright (c) 1995, 2009, Innobase Oy. All Rights Reserved.
|
Copyright (c) 1995, 2012, Oracle and/or its affiliates. All Rights Reserved.
|
||||||
|
|
||||||
This program is free software; you can redistribute it and/or modify it under
|
This program is free software; you can redistribute it and/or modify it under
|
||||||
the terms of the GNU General Public License as published by the Free Software
|
the terms of the GNU General Public License as published by the Free Software
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
/*****************************************************************************
|
/*****************************************************************************
|
||||||
|
|
||||||
Copyright (c) 1994, 2009, Innobase Oy. All Rights Reserved.
|
Copyright (c) 1994, 2012, Oracle and/or its affiliates. All Rights Reserved.
|
||||||
|
|
||||||
This program is free software; you can redistribute it and/or modify it under
|
This program is free software; you can redistribute it and/or modify it under
|
||||||
the terms of the GNU General Public License as published by the Free Software
|
the terms of the GNU General Public License as published by the Free Software
|
||||||
@ -11,8 +11,8 @@ ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
|||||||
FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
|
FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
|
||||||
|
|
||||||
You should have received a copy of the GNU General Public License along with
|
You should have received a copy of the GNU General Public License along with
|
||||||
this program; if not, write to the Free Software Foundation, Inc., 59 Temple
|
this program; if not, write to the Free Software Foundation, Inc.,
|
||||||
Place, Suite 330, Boston, MA 02111-1307 USA
|
51 Franklin Street, Suite 500, Boston, MA 02110-1335 USA
|
||||||
|
|
||||||
*****************************************************************************/
|
*****************************************************************************/
|
||||||
|
|
||||||
@ -1180,14 +1180,15 @@ page_cur_insert_rec_zip_reorg(
|
|||||||
/* Before trying to reorganize the page,
|
/* Before trying to reorganize the page,
|
||||||
store the number of preceding records on the page. */
|
store the number of preceding records on the page. */
|
||||||
pos = page_rec_get_n_recs_before(rec);
|
pos = page_rec_get_n_recs_before(rec);
|
||||||
|
ut_ad(pos > 0);
|
||||||
|
|
||||||
if (page_zip_reorganize(block, index, mtr)) {
|
if (page_zip_reorganize(block, index, mtr)) {
|
||||||
/* The page was reorganized: Find rec by seeking to pos,
|
/* The page was reorganized: Find rec by seeking to pos,
|
||||||
and update *current_rec. */
|
and update *current_rec. */
|
||||||
rec = page + PAGE_NEW_INFIMUM;
|
if (pos > 1) {
|
||||||
|
rec = page_rec_get_nth(page, pos - 1);
|
||||||
while (--pos) {
|
} else {
|
||||||
rec = page + rec_get_next_offs(rec, TRUE);
|
rec = page + PAGE_NEW_INFIMUM;
|
||||||
}
|
}
|
||||||
|
|
||||||
*current_rec = rec;
|
*current_rec = rec;
|
||||||
@ -1283,6 +1284,12 @@ page_cur_insert_rec_zip(
|
|||||||
insert_rec = page_cur_insert_rec_zip_reorg(
|
insert_rec = page_cur_insert_rec_zip_reorg(
|
||||||
current_rec, block, index, insert_rec,
|
current_rec, block, index, insert_rec,
|
||||||
page, page_zip, mtr);
|
page, page_zip, mtr);
|
||||||
|
#ifdef UNIV_DEBUG
|
||||||
|
if (insert_rec) {
|
||||||
|
rec_offs_make_valid(
|
||||||
|
insert_rec, index, offsets);
|
||||||
|
}
|
||||||
|
#endif /* UNIV_DEBUG */
|
||||||
}
|
}
|
||||||
|
|
||||||
return(insert_rec);
|
return(insert_rec);
|
||||||
|
@ -11,8 +11,8 @@ ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
|||||||
FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
|
FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
|
||||||
|
|
||||||
You should have received a copy of the GNU General Public License along with
|
You should have received a copy of the GNU General Public License along with
|
||||||
this program; if not, write to the Free Software Foundation, Inc., 59 Temple
|
this program; if not, write to the Free Software Foundation, Inc.,
|
||||||
Place, Suite 330, Boston, MA 02111-1307 USA
|
51 Franklin Street, Suite 500, Boston, MA 02110-1335 USA
|
||||||
|
|
||||||
*****************************************************************************/
|
*****************************************************************************/
|
||||||
|
|
||||||
@ -1454,55 +1454,54 @@ page_dir_balance_slot(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifndef UNIV_HOTBACKUP
|
|
||||||
/************************************************************//**
|
/************************************************************//**
|
||||||
Returns the middle record of the record list. If there are an even number
|
Returns the nth record of the record list.
|
||||||
of records in the list, returns the first record of the upper half-list.
|
This is the inverse function of page_rec_get_n_recs_before().
|
||||||
@return middle record */
|
@return nth record */
|
||||||
UNIV_INTERN
|
UNIV_INTERN
|
||||||
rec_t*
|
const rec_t*
|
||||||
page_get_middle_rec(
|
page_rec_get_nth_const(
|
||||||
/*================*/
|
/*===================*/
|
||||||
page_t* page) /*!< in: page */
|
const page_t* page, /*!< in: page */
|
||||||
|
ulint nth) /*!< in: nth record */
|
||||||
{
|
{
|
||||||
page_dir_slot_t* slot;
|
const page_dir_slot_t* slot;
|
||||||
ulint middle;
|
|
||||||
ulint i;
|
ulint i;
|
||||||
ulint n_owned;
|
ulint n_owned;
|
||||||
ulint count;
|
const rec_t* rec;
|
||||||
rec_t* rec;
|
|
||||||
|
|
||||||
/* This many records we must leave behind */
|
ut_ad(nth < UNIV_PAGE_SIZE / (REC_N_NEW_EXTRA_BYTES + 1));
|
||||||
middle = (page_get_n_recs(page) + PAGE_HEAP_NO_USER_LOW) / 2;
|
|
||||||
|
|
||||||
count = 0;
|
|
||||||
|
|
||||||
for (i = 0;; i++) {
|
for (i = 0;; i++) {
|
||||||
|
|
||||||
slot = page_dir_get_nth_slot(page, i);
|
slot = page_dir_get_nth_slot(page, i);
|
||||||
n_owned = page_dir_slot_get_n_owned(slot);
|
n_owned = page_dir_slot_get_n_owned(slot);
|
||||||
|
|
||||||
if (count + n_owned > middle) {
|
if (n_owned > nth) {
|
||||||
break;
|
break;
|
||||||
} else {
|
} else {
|
||||||
count += n_owned;
|
nth -= n_owned;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ut_ad(i > 0);
|
ut_ad(i > 0);
|
||||||
slot = page_dir_get_nth_slot(page, i - 1);
|
slot = page_dir_get_nth_slot(page, i - 1);
|
||||||
rec = (rec_t*) page_dir_slot_get_rec(slot);
|
rec = page_dir_slot_get_rec(slot);
|
||||||
rec = page_rec_get_next(rec);
|
|
||||||
|
|
||||||
/* There are now count records behind rec */
|
if (page_is_comp(page)) {
|
||||||
|
do {
|
||||||
for (i = 0; i < middle - count; i++) {
|
rec = page_rec_get_next_low(rec, TRUE);
|
||||||
rec = page_rec_get_next(rec);
|
ut_ad(rec);
|
||||||
|
} while (nth--);
|
||||||
|
} else {
|
||||||
|
do {
|
||||||
|
rec = page_rec_get_next_low(rec, FALSE);
|
||||||
|
ut_ad(rec);
|
||||||
|
} while (nth--);
|
||||||
}
|
}
|
||||||
|
|
||||||
return(rec);
|
return(rec);
|
||||||
}
|
}
|
||||||
#endif /* !UNIV_HOTBACKUP */
|
|
||||||
|
|
||||||
/***************************************************************//**
|
/***************************************************************//**
|
||||||
Returns the number of records before the given record in chain.
|
Returns the number of records before the given record in chain.
|
||||||
@ -1564,6 +1563,7 @@ page_rec_get_n_recs_before(
|
|||||||
n--;
|
n--;
|
||||||
|
|
||||||
ut_ad(n >= 0);
|
ut_ad(n >= 0);
|
||||||
|
ut_ad(n < UNIV_PAGE_SIZE / (REC_N_NEW_EXTRA_BYTES + 1));
|
||||||
|
|
||||||
return((ulint) n);
|
return((ulint) n);
|
||||||
}
|
}
|
||||||
|
@ -11,8 +11,8 @@ ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
|||||||
FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
|
FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
|
||||||
|
|
||||||
You should have received a copy of the GNU General Public License along with
|
You should have received a copy of the GNU General Public License along with
|
||||||
this program; if not, write to the Free Software Foundation, Inc., 59 Temple
|
this program; if not, write to the Free Software Foundation, Inc.,
|
||||||
Place, Suite 330, Boston, MA 02111-1307 USA
|
51 Franklin Street, Suite 500, Boston, MA 02110-1335 USA
|
||||||
|
|
||||||
*****************************************************************************/
|
*****************************************************************************/
|
||||||
|
|
||||||
@ -23,7 +23,6 @@ Insert into a table
|
|||||||
Created 4/20/1996 Heikki Tuuri
|
Created 4/20/1996 Heikki Tuuri
|
||||||
*******************************************************/
|
*******************************************************/
|
||||||
|
|
||||||
#include "my_global.h" /* HAVE_* */
|
|
||||||
#include "m_string.h" /* for my_sys.h */
|
#include "m_string.h" /* for my_sys.h */
|
||||||
#include "my_sys.h" /* DEBUG_SYNC_C */
|
#include "my_sys.h" /* DEBUG_SYNC_C */
|
||||||
#include "row0ins.h"
|
#include "row0ins.h"
|
||||||
@ -351,9 +350,9 @@ row_ins_clust_index_entry_by_modify(
|
|||||||
return(DB_LOCK_TABLE_FULL);
|
return(DB_LOCK_TABLE_FULL);
|
||||||
|
|
||||||
}
|
}
|
||||||
err = btr_cur_pessimistic_update(0, cursor,
|
err = btr_cur_pessimistic_update(
|
||||||
heap, big_rec, update,
|
BTR_KEEP_POS_FLAG, cursor, heap, big_rec, update,
|
||||||
0, thr, mtr);
|
0, thr, mtr);
|
||||||
}
|
}
|
||||||
|
|
||||||
return(err);
|
return(err);
|
||||||
@ -1982,6 +1981,7 @@ row_ins_index_entry_low(
|
|||||||
ulint modify = 0; /* remove warning */
|
ulint modify = 0; /* remove warning */
|
||||||
rec_t* insert_rec;
|
rec_t* insert_rec;
|
||||||
rec_t* rec;
|
rec_t* rec;
|
||||||
|
ulint* offsets;
|
||||||
ulint err;
|
ulint err;
|
||||||
ulint n_unique;
|
ulint n_unique;
|
||||||
big_rec_t* big_rec = NULL;
|
big_rec_t* big_rec = NULL;
|
||||||
@ -2089,6 +2089,64 @@ row_ins_index_entry_low(
|
|||||||
err = row_ins_clust_index_entry_by_modify(
|
err = row_ins_clust_index_entry_by_modify(
|
||||||
mode, &cursor, &heap, &big_rec, entry,
|
mode, &cursor, &heap, &big_rec, entry,
|
||||||
thr, &mtr);
|
thr, &mtr);
|
||||||
|
|
||||||
|
if (big_rec) {
|
||||||
|
ut_a(err == DB_SUCCESS);
|
||||||
|
/* Write out the externally stored
|
||||||
|
columns while still x-latching
|
||||||
|
index->lock and block->lock. Allocate
|
||||||
|
pages for big_rec in the mtr that
|
||||||
|
modified the B-tree, but be sure to skip
|
||||||
|
any pages that were freed in mtr. We will
|
||||||
|
write out the big_rec pages before
|
||||||
|
committing the B-tree mini-transaction. If
|
||||||
|
the system crashes so that crash recovery
|
||||||
|
will not replay the mtr_commit(&mtr), the
|
||||||
|
big_rec pages will be left orphaned until
|
||||||
|
the pages are allocated for something else.
|
||||||
|
|
||||||
|
TODO: If the allocation extends the
|
||||||
|
tablespace, it will not be redo
|
||||||
|
logged, in either mini-transaction.
|
||||||
|
Tablespace extension should be
|
||||||
|
redo-logged in the big_rec
|
||||||
|
mini-transaction, so that recovery
|
||||||
|
will not fail when the big_rec was
|
||||||
|
written to the extended portion of the
|
||||||
|
file, in case the file was somehow
|
||||||
|
truncated in the crash. */
|
||||||
|
|
||||||
|
rec = btr_cur_get_rec(&cursor);
|
||||||
|
offsets = rec_get_offsets(
|
||||||
|
rec, index, NULL,
|
||||||
|
ULINT_UNDEFINED, &heap);
|
||||||
|
|
||||||
|
DEBUG_SYNC_C("before_row_ins_upd_extern");
|
||||||
|
err = btr_store_big_rec_extern_fields(
|
||||||
|
index, btr_cur_get_block(&cursor),
|
||||||
|
rec, offsets, big_rec, &mtr,
|
||||||
|
BTR_STORE_INSERT_UPDATE);
|
||||||
|
DEBUG_SYNC_C("after_row_ins_upd_extern");
|
||||||
|
/* If writing big_rec fails (for
|
||||||
|
example, because of DB_OUT_OF_FILE_SPACE),
|
||||||
|
the record will be corrupted. Even if
|
||||||
|
we did not update any externally
|
||||||
|
stored columns, our update could cause
|
||||||
|
the record to grow so that a
|
||||||
|
non-updated column was selected for
|
||||||
|
external storage. This non-update
|
||||||
|
would not have been written to the
|
||||||
|
undo log, and thus the record cannot
|
||||||
|
be rolled back.
|
||||||
|
|
||||||
|
However, because we have not executed
|
||||||
|
mtr_commit(mtr) yet, the update will
|
||||||
|
not be replayed in crash recovery, and
|
||||||
|
the following assertion failure will
|
||||||
|
effectively "roll back" the operation. */
|
||||||
|
ut_a(err == DB_SUCCESS);
|
||||||
|
goto stored_big_rec;
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
ut_ad(!n_ext);
|
ut_ad(!n_ext);
|
||||||
err = row_ins_sec_index_entry_by_modify(
|
err = row_ins_sec_index_entry_by_modify(
|
||||||
@ -2117,9 +2175,6 @@ function_exit:
|
|||||||
mtr_commit(&mtr);
|
mtr_commit(&mtr);
|
||||||
|
|
||||||
if (UNIV_LIKELY_NULL(big_rec)) {
|
if (UNIV_LIKELY_NULL(big_rec)) {
|
||||||
rec_t* rec;
|
|
||||||
ulint* offsets;
|
|
||||||
|
|
||||||
DBUG_EXECUTE_IF(
|
DBUG_EXECUTE_IF(
|
||||||
"row_ins_extern_checkpoint",
|
"row_ins_extern_checkpoint",
|
||||||
log_make_checkpoint_at(IB_ULONGLONG_MAX, TRUE););
|
log_make_checkpoint_at(IB_ULONGLONG_MAX, TRUE););
|
||||||
@ -2134,12 +2189,13 @@ function_exit:
|
|||||||
offsets = rec_get_offsets(rec, index, NULL,
|
offsets = rec_get_offsets(rec, index, NULL,
|
||||||
ULINT_UNDEFINED, &heap);
|
ULINT_UNDEFINED, &heap);
|
||||||
|
|
||||||
DEBUG_SYNC_C("before_row_ins_upd_extern");
|
DEBUG_SYNC_C("before_row_ins_extern");
|
||||||
err = btr_store_big_rec_extern_fields(
|
err = btr_store_big_rec_extern_fields(
|
||||||
index, btr_cur_get_block(&cursor),
|
index, btr_cur_get_block(&cursor),
|
||||||
rec, offsets, &mtr, FALSE, big_rec);
|
rec, offsets, big_rec, &mtr, BTR_STORE_INSERT);
|
||||||
DEBUG_SYNC_C("after_row_ins_upd_extern");
|
DEBUG_SYNC_C("after_row_ins_extern");
|
||||||
|
|
||||||
|
stored_big_rec:
|
||||||
if (modify) {
|
if (modify) {
|
||||||
dtuple_big_rec_free(big_rec);
|
dtuple_big_rec_free(big_rec);
|
||||||
} else {
|
} else {
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
/*****************************************************************************
|
/*****************************************************************************
|
||||||
|
|
||||||
Copyright (c) 1996, 2011, Oracle and/or its affiliates. All Rights Reserved.
|
Copyright (c) 1996, 2012, Oracle and/or its affiliates. All Rights Reserved.
|
||||||
|
|
||||||
This program is free software; you can redistribute it and/or modify it under
|
This program is free software; you can redistribute it and/or modify it under
|
||||||
the terms of the GNU General Public License as published by the Free Software
|
the terms of the GNU General Public License as published by the Free Software
|
||||||
@ -11,8 +11,8 @@ ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
|||||||
FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
|
FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
|
||||||
|
|
||||||
You should have received a copy of the GNU General Public License along with
|
You should have received a copy of the GNU General Public License along with
|
||||||
this program; if not, write to the Free Software Foundation, Inc., 59 Temple
|
this program; if not, write to the Free Software Foundation, Inc.,
|
||||||
Place, Suite 330, Boston, MA 02111-1307 USA
|
51 Franklin Street, Suite 500, Boston, MA 02110-1335 USA
|
||||||
|
|
||||||
*****************************************************************************/
|
*****************************************************************************/
|
||||||
|
|
||||||
@ -241,13 +241,22 @@ row_build(
|
|||||||
ut_ad(rec_offs_validate(rec, index, offsets));
|
ut_ad(rec_offs_validate(rec, index, offsets));
|
||||||
}
|
}
|
||||||
|
|
||||||
#if 0 && defined UNIV_BLOB_NULL_DEBUG
|
#ifdef UNIV_BLOB_NULL_DEBUG
|
||||||
/* This one can fail in trx_rollback_active() if
|
if (rec_offs_any_null_extern(rec, offsets)) {
|
||||||
the server crashed during an insert before the
|
/* This condition can occur during crash recovery
|
||||||
btr_store_big_rec_extern_fields() did mtr_commit()
|
before trx_rollback_active() has completed execution.
|
||||||
all BLOB pointers to the clustered index record. */
|
|
||||||
ut_a(!rec_offs_any_null_extern(rec, offsets));
|
This condition is possible if the server crashed
|
||||||
#endif /* 0 && UNIV_BLOB_NULL_DEBUG */
|
during an insert or update-by-delete-and-insert before
|
||||||
|
btr_store_big_rec_extern_fields() did mtr_commit() all
|
||||||
|
BLOB pointers to the freshly inserted clustered index
|
||||||
|
record. */
|
||||||
|
ut_a(trx_assert_recovered(
|
||||||
|
row_get_rec_trx_id(rec, index, offsets)));
|
||||||
|
ut_a(trx_undo_roll_ptr_is_insert(
|
||||||
|
row_get_rec_roll_ptr(rec, index, offsets)));
|
||||||
|
}
|
||||||
|
#endif /* UNIV_BLOB_NULL_DEBUG */
|
||||||
|
|
||||||
if (type != ROW_COPY_POINTERS) {
|
if (type != ROW_COPY_POINTERS) {
|
||||||
/* Take a copy of rec to heap */
|
/* Take a copy of rec to heap */
|
||||||
|
@ -11,8 +11,8 @@ ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
|||||||
FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
|
FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
|
||||||
|
|
||||||
You should have received a copy of the GNU General Public License along with
|
You should have received a copy of the GNU General Public License along with
|
||||||
this program; if not, write to the Free Software Foundation, Inc., 59 Temple
|
this program; if not, write to the Free Software Foundation, Inc.,
|
||||||
Place, Suite 330, Boston, MA 02111-1307 USA
|
51 Franklin Street, Suite 500, Boston, MA 02110-1335 USA
|
||||||
|
|
||||||
*****************************************************************************/
|
*****************************************************************************/
|
||||||
|
|
||||||
@ -23,7 +23,6 @@ Update of a row
|
|||||||
Created 12/27/1996 Heikki Tuuri
|
Created 12/27/1996 Heikki Tuuri
|
||||||
*******************************************************/
|
*******************************************************/
|
||||||
|
|
||||||
#include "my_global.h" /* HAVE_* */
|
|
||||||
#include "m_string.h" /* for my_sys.h */
|
#include "m_string.h" /* for my_sys.h */
|
||||||
#include "my_sys.h" /* DEBUG_SYNC_C */
|
#include "my_sys.h" /* DEBUG_SYNC_C */
|
||||||
#include "row0upd.h"
|
#include "row0upd.h"
|
||||||
@ -2003,33 +2002,62 @@ row_upd_clust_rec(
|
|||||||
ut_ad(!rec_get_deleted_flag(btr_pcur_get_rec(pcur),
|
ut_ad(!rec_get_deleted_flag(btr_pcur_get_rec(pcur),
|
||||||
dict_table_is_comp(index->table)));
|
dict_table_is_comp(index->table)));
|
||||||
|
|
||||||
err = btr_cur_pessimistic_update(BTR_NO_LOCKING_FLAG, btr_cur,
|
err = btr_cur_pessimistic_update(
|
||||||
&heap, &big_rec, node->update,
|
BTR_NO_LOCKING_FLAG | BTR_KEEP_POS_FLAG, btr_cur,
|
||||||
node->cmpl_info, thr, mtr);
|
&heap, &big_rec, node->update, node->cmpl_info, thr, mtr);
|
||||||
mtr_commit(mtr);
|
if (big_rec) {
|
||||||
|
ulint offsets_[REC_OFFS_NORMAL_SIZE];
|
||||||
if (err == DB_SUCCESS && big_rec) {
|
rec_t* rec;
|
||||||
ulint offsets_[REC_OFFS_NORMAL_SIZE];
|
|
||||||
rec_t* rec;
|
|
||||||
rec_offs_init(offsets_);
|
rec_offs_init(offsets_);
|
||||||
|
|
||||||
DBUG_EXECUTE_IF(
|
ut_a(err == DB_SUCCESS);
|
||||||
"row_upd_extern_checkpoint",
|
/* Write out the externally stored
|
||||||
log_make_checkpoint_at(IB_ULONGLONG_MAX, TRUE););
|
columns while still x-latching
|
||||||
|
index->lock and block->lock. Allocate
|
||||||
|
pages for big_rec in the mtr that
|
||||||
|
modified the B-tree, but be sure to skip
|
||||||
|
any pages that were freed in mtr. We will
|
||||||
|
write out the big_rec pages before
|
||||||
|
committing the B-tree mini-transaction. If
|
||||||
|
the system crashes so that crash recovery
|
||||||
|
will not replay the mtr_commit(&mtr), the
|
||||||
|
big_rec pages will be left orphaned until
|
||||||
|
the pages are allocated for something else.
|
||||||
|
|
||||||
|
TODO: If the allocation extends the tablespace, it
|
||||||
|
will not be redo logged, in either mini-transaction.
|
||||||
|
Tablespace extension should be redo-logged in the
|
||||||
|
big_rec mini-transaction, so that recovery will not
|
||||||
|
fail when the big_rec was written to the extended
|
||||||
|
portion of the file, in case the file was somehow
|
||||||
|
truncated in the crash. */
|
||||||
|
|
||||||
mtr_start(mtr);
|
|
||||||
ut_a(btr_pcur_restore_position(BTR_MODIFY_TREE, pcur, mtr));
|
|
||||||
rec = btr_cur_get_rec(btr_cur);
|
rec = btr_cur_get_rec(btr_cur);
|
||||||
DEBUG_SYNC_C("before_row_upd_extern");
|
DEBUG_SYNC_C("before_row_upd_extern");
|
||||||
err = btr_store_big_rec_extern_fields(
|
err = btr_store_big_rec_extern_fields(
|
||||||
index, btr_cur_get_block(btr_cur), rec,
|
index, btr_cur_get_block(btr_cur), rec,
|
||||||
rec_get_offsets(rec, index, offsets_,
|
rec_get_offsets(rec, index, offsets_,
|
||||||
ULINT_UNDEFINED, &heap),
|
ULINT_UNDEFINED, &heap),
|
||||||
mtr, TRUE, big_rec);
|
big_rec, mtr, BTR_STORE_UPDATE);
|
||||||
DEBUG_SYNC_C("after_row_upd_extern");
|
DEBUG_SYNC_C("after_row_upd_extern");
|
||||||
mtr_commit(mtr);
|
/* If writing big_rec fails (for example, because of
|
||||||
|
DB_OUT_OF_FILE_SPACE), the record will be corrupted.
|
||||||
|
Even if we did not update any externally stored
|
||||||
|
columns, our update could cause the record to grow so
|
||||||
|
that a non-updated column was selected for external
|
||||||
|
storage. This non-update would not have been written
|
||||||
|
to the undo log, and thus the record cannot be rolled
|
||||||
|
back.
|
||||||
|
|
||||||
|
However, because we have not executed mtr_commit(mtr)
|
||||||
|
yet, the update will not be replayed in crash
|
||||||
|
recovery, and the following assertion failure will
|
||||||
|
effectively "roll back" the operation. */
|
||||||
|
ut_a(err == DB_SUCCESS);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
mtr_commit(mtr);
|
||||||
|
|
||||||
if (UNIV_LIKELY_NULL(heap)) {
|
if (UNIV_LIKELY_NULL(heap)) {
|
||||||
mem_heap_free(heap);
|
mem_heap_free(heap);
|
||||||
}
|
}
|
||||||
|
@ -11,8 +11,8 @@ ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
|||||||
FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
|
FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
|
||||||
|
|
||||||
You should have received a copy of the GNU General Public License along with
|
You should have received a copy of the GNU General Public License along with
|
||||||
this program; if not, write to the Free Software Foundation, Inc., 59 Temple
|
this program; if not, write to the Free Software Foundation, Inc.,
|
||||||
Place, Suite 330, Boston, MA 02111-1307 USA
|
51 Franklin Street, Suite 500, Boston, MA 02110-1335 USA
|
||||||
|
|
||||||
*****************************************************************************/
|
*****************************************************************************/
|
||||||
|
|
||||||
@ -1198,6 +1198,7 @@ trx_undo_report_row_operation(
|
|||||||
trx_t* trx;
|
trx_t* trx;
|
||||||
trx_undo_t* undo;
|
trx_undo_t* undo;
|
||||||
ulint page_no;
|
ulint page_no;
|
||||||
|
buf_block_t* undo_block;
|
||||||
trx_rseg_t* rseg;
|
trx_rseg_t* rseg;
|
||||||
mtr_t mtr;
|
mtr_t mtr;
|
||||||
ulint err = DB_SUCCESS;
|
ulint err = DB_SUCCESS;
|
||||||
@ -1240,10 +1241,13 @@ trx_undo_report_row_operation(
|
|||||||
|
|
||||||
if (UNIV_UNLIKELY(!undo)) {
|
if (UNIV_UNLIKELY(!undo)) {
|
||||||
/* Did not succeed */
|
/* Did not succeed */
|
||||||
|
ut_ad(err != DB_SUCCESS);
|
||||||
mutex_exit(&(trx->undo_mutex));
|
mutex_exit(&(trx->undo_mutex));
|
||||||
|
|
||||||
return(err);
|
return(err);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ut_ad(err == DB_SUCCESS);
|
||||||
} else {
|
} else {
|
||||||
ut_ad(op_type == TRX_UNDO_MODIFY_OP);
|
ut_ad(op_type == TRX_UNDO_MODIFY_OP);
|
||||||
|
|
||||||
@ -1257,30 +1261,30 @@ trx_undo_report_row_operation(
|
|||||||
|
|
||||||
if (UNIV_UNLIKELY(!undo)) {
|
if (UNIV_UNLIKELY(!undo)) {
|
||||||
/* Did not succeed */
|
/* Did not succeed */
|
||||||
|
ut_ad(err != DB_SUCCESS);
|
||||||
mutex_exit(&(trx->undo_mutex));
|
mutex_exit(&(trx->undo_mutex));
|
||||||
return(err);
|
return(err);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ut_ad(err == DB_SUCCESS);
|
||||||
offsets = rec_get_offsets(rec, index, offsets,
|
offsets = rec_get_offsets(rec, index, offsets,
|
||||||
ULINT_UNDEFINED, &heap);
|
ULINT_UNDEFINED, &heap);
|
||||||
}
|
}
|
||||||
|
|
||||||
page_no = undo->last_page_no;
|
|
||||||
|
|
||||||
mtr_start(&mtr);
|
mtr_start(&mtr);
|
||||||
|
|
||||||
|
page_no = undo->last_page_no;
|
||||||
|
undo_block = buf_page_get_gen(
|
||||||
|
undo->space, undo->zip_size, page_no, RW_X_LATCH,
|
||||||
|
undo->guess_block, BUF_GET, __FILE__, __LINE__, &mtr);
|
||||||
|
buf_block_dbg_add_level(undo_block, SYNC_TRX_UNDO_PAGE);
|
||||||
|
|
||||||
do {
|
do {
|
||||||
buf_block_t* undo_block;
|
|
||||||
page_t* undo_page;
|
page_t* undo_page;
|
||||||
ulint offset;
|
ulint offset;
|
||||||
|
|
||||||
undo_block = buf_page_get_gen(undo->space, undo->zip_size,
|
|
||||||
page_no, RW_X_LATCH,
|
|
||||||
undo->guess_block, BUF_GET,
|
|
||||||
__FILE__, __LINE__, &mtr);
|
|
||||||
buf_block_dbg_add_level(undo_block, SYNC_TRX_UNDO_PAGE);
|
|
||||||
|
|
||||||
undo_page = buf_block_get_frame(undo_block);
|
undo_page = buf_block_get_frame(undo_block);
|
||||||
|
ut_ad(page_no == buf_block_get_page_no(undo_block));
|
||||||
|
|
||||||
if (op_type == TRX_UNDO_INSERT_OP) {
|
if (op_type == TRX_UNDO_INSERT_OP) {
|
||||||
offset = trx_undo_page_report_insert(
|
offset = trx_undo_page_report_insert(
|
||||||
@ -1357,12 +1361,11 @@ trx_undo_report_row_operation(
|
|||||||
a pessimistic insert in a B-tree, and we must reserve the
|
a pessimistic insert in a B-tree, and we must reserve the
|
||||||
counterpart of the tree latch, which is the rseg mutex. */
|
counterpart of the tree latch, which is the rseg mutex. */
|
||||||
|
|
||||||
mutex_enter(&(rseg->mutex));
|
mutex_enter(&rseg->mutex);
|
||||||
|
undo_block = trx_undo_add_page(trx, undo, &mtr);
|
||||||
page_no = trx_undo_add_page(trx, undo, &mtr);
|
mutex_exit(&rseg->mutex);
|
||||||
|
page_no = undo->last_page_no;
|
||||||
mutex_exit(&(rseg->mutex));
|
} while (undo_block != NULL);
|
||||||
} while (UNIV_LIKELY(page_no != FIL_NULL));
|
|
||||||
|
|
||||||
/* Did not succeed: out of space */
|
/* Did not succeed: out of space */
|
||||||
err = DB_OUT_OF_FILE_SPACE;
|
err = DB_OUT_OF_FILE_SPACE;
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
/*****************************************************************************
|
/*****************************************************************************
|
||||||
|
|
||||||
Copyright (c) 1996, 2011, Innobase Oy. All Rights Reserved.
|
Copyright (c) 1996, 2012, Oracle and/or its affiliates. All Rights Reserved.
|
||||||
|
|
||||||
This program is free software; you can redistribute it and/or modify it under
|
This program is free software; you can redistribute it and/or modify it under
|
||||||
the terms of the GNU General Public License as published by the Free Software
|
the terms of the GNU General Public License as published by the Free Software
|
||||||
@ -11,8 +11,8 @@ ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
|||||||
FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
|
FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
|
||||||
|
|
||||||
You should have received a copy of the GNU General Public License along with
|
You should have received a copy of the GNU General Public License along with
|
||||||
this program; if not, write to the Free Software Foundation, Inc., 59 Temple
|
this program; if not, write to the Free Software Foundation, Inc.,
|
||||||
Place, Suite 330, Boston, MA 02111-1307 USA
|
51 Franklin Street, Suite 500, Boston, MA 02110-1335 USA
|
||||||
|
|
||||||
*****************************************************************************/
|
*****************************************************************************/
|
||||||
|
|
||||||
@ -255,9 +255,7 @@ trx_sys_create_doublewrite_buf(void)
|
|||||||
{
|
{
|
||||||
buf_block_t* block;
|
buf_block_t* block;
|
||||||
buf_block_t* block2;
|
buf_block_t* block2;
|
||||||
#ifdef UNIV_SYNC_DEBUG
|
|
||||||
buf_block_t* new_block;
|
buf_block_t* new_block;
|
||||||
#endif /* UNIV_SYNC_DEBUG */
|
|
||||||
byte* doublewrite;
|
byte* doublewrite;
|
||||||
byte* fseg_header;
|
byte* fseg_header;
|
||||||
ulint page_no;
|
ulint page_no;
|
||||||
@ -336,10 +334,9 @@ start_again:
|
|||||||
|
|
||||||
for (i = 0; i < 2 * TRX_SYS_DOUBLEWRITE_BLOCK_SIZE
|
for (i = 0; i < 2 * TRX_SYS_DOUBLEWRITE_BLOCK_SIZE
|
||||||
+ FSP_EXTENT_SIZE / 2; i++) {
|
+ FSP_EXTENT_SIZE / 2; i++) {
|
||||||
page_no = fseg_alloc_free_page(fseg_header,
|
new_block = fseg_alloc_free_page(
|
||||||
prev_page_no + 1,
|
fseg_header, prev_page_no + 1, FSP_UP, &mtr);
|
||||||
FSP_UP, &mtr);
|
if (new_block == NULL) {
|
||||||
if (page_no == FIL_NULL) {
|
|
||||||
fprintf(stderr,
|
fprintf(stderr,
|
||||||
"InnoDB: Cannot create doublewrite"
|
"InnoDB: Cannot create doublewrite"
|
||||||
" buffer: you must\n"
|
" buffer: you must\n"
|
||||||
@ -360,13 +357,8 @@ start_again:
|
|||||||
the page position in the tablespace, then the page
|
the page position in the tablespace, then the page
|
||||||
has not been written to in doublewrite. */
|
has not been written to in doublewrite. */
|
||||||
|
|
||||||
#ifdef UNIV_SYNC_DEBUG
|
ut_ad(rw_lock_get_x_lock_count(&new_block->lock) == 1);
|
||||||
new_block =
|
page_no = buf_block_get_page_no(new_block);
|
||||||
#endif /* UNIV_SYNC_DEBUG */
|
|
||||||
buf_page_get(TRX_SYS_SPACE, 0, page_no,
|
|
||||||
RW_X_LATCH, &mtr);
|
|
||||||
buf_block_dbg_add_level(new_block,
|
|
||||||
SYNC_NO_ORDER_CHECK);
|
|
||||||
|
|
||||||
if (i == FSP_EXTENT_SIZE / 2) {
|
if (i == FSP_EXTENT_SIZE / 2) {
|
||||||
ut_a(page_no == FSP_EXTENT_SIZE);
|
ut_a(page_no == FSP_EXTENT_SIZE);
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
/*****************************************************************************
|
/*****************************************************************************
|
||||||
|
|
||||||
Copyright (c) 1996, 2009, Innobase Oy. All Rights Reserved.
|
Copyright (c) 1996, 2012, Oracle and/or its affiliates. All Rights Reserved.
|
||||||
|
|
||||||
This program is free software; you can redistribute it and/or modify it under
|
This program is free software; you can redistribute it and/or modify it under
|
||||||
the terms of the GNU General Public License as published by the Free Software
|
the terms of the GNU General Public License as published by the Free Software
|
||||||
@ -11,8 +11,8 @@ ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
|||||||
FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
|
FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
|
||||||
|
|
||||||
You should have received a copy of the GNU General Public License along with
|
You should have received a copy of the GNU General Public License along with
|
||||||
this program; if not, write to the Free Software Foundation, Inc., 59 Temple
|
this program; if not, write to the Free Software Foundation, Inc.,
|
||||||
Place, Suite 330, Boston, MA 02111-1307 USA
|
51 Franklin Street, Suite 500, Boston, MA 02110-1335 USA
|
||||||
|
|
||||||
*****************************************************************************/
|
*****************************************************************************/
|
||||||
|
|
||||||
@ -876,9 +876,9 @@ trx_undo_discard_latest_update_undo(
|
|||||||
#ifndef UNIV_HOTBACKUP
|
#ifndef UNIV_HOTBACKUP
|
||||||
/********************************************************************//**
|
/********************************************************************//**
|
||||||
Tries to add a page to the undo log segment where the undo log is placed.
|
Tries to add a page to the undo log segment where the undo log is placed.
|
||||||
@return page number if success, else FIL_NULL */
|
@return X-latched block if success, else NULL */
|
||||||
UNIV_INTERN
|
UNIV_INTERN
|
||||||
ulint
|
buf_block_t*
|
||||||
trx_undo_add_page(
|
trx_undo_add_page(
|
||||||
/*==============*/
|
/*==============*/
|
||||||
trx_t* trx, /*!< in: transaction */
|
trx_t* trx, /*!< in: transaction */
|
||||||
@ -888,11 +888,10 @@ trx_undo_add_page(
|
|||||||
the rollback segment mutex */
|
the rollback segment mutex */
|
||||||
{
|
{
|
||||||
page_t* header_page;
|
page_t* header_page;
|
||||||
|
buf_block_t* new_block;
|
||||||
page_t* new_page;
|
page_t* new_page;
|
||||||
trx_rseg_t* rseg;
|
trx_rseg_t* rseg;
|
||||||
ulint page_no;
|
|
||||||
ulint n_reserved;
|
ulint n_reserved;
|
||||||
ibool success;
|
|
||||||
|
|
||||||
ut_ad(mutex_own(&(trx->undo_mutex)));
|
ut_ad(mutex_own(&(trx->undo_mutex)));
|
||||||
ut_ad(!mutex_own(&kernel_mutex));
|
ut_ad(!mutex_own(&kernel_mutex));
|
||||||
@ -902,37 +901,37 @@ trx_undo_add_page(
|
|||||||
|
|
||||||
if (rseg->curr_size == rseg->max_size) {
|
if (rseg->curr_size == rseg->max_size) {
|
||||||
|
|
||||||
return(FIL_NULL);
|
return(NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
header_page = trx_undo_page_get(undo->space, undo->zip_size,
|
header_page = trx_undo_page_get(undo->space, undo->zip_size,
|
||||||
undo->hdr_page_no, mtr);
|
undo->hdr_page_no, mtr);
|
||||||
|
|
||||||
success = fsp_reserve_free_extents(&n_reserved, undo->space, 1,
|
if (!fsp_reserve_free_extents(&n_reserved, undo->space, 1,
|
||||||
FSP_UNDO, mtr);
|
FSP_UNDO, mtr)) {
|
||||||
if (!success) {
|
|
||||||
|
|
||||||
return(FIL_NULL);
|
return(NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
page_no = fseg_alloc_free_page_general(header_page + TRX_UNDO_SEG_HDR
|
new_block = fseg_alloc_free_page_general(
|
||||||
+ TRX_UNDO_FSEG_HEADER,
|
TRX_UNDO_SEG_HDR + TRX_UNDO_FSEG_HEADER
|
||||||
undo->top_page_no + 1, FSP_UP,
|
+ header_page,
|
||||||
TRUE, mtr);
|
undo->top_page_no + 1, FSP_UP, TRUE, mtr, mtr);
|
||||||
|
|
||||||
fil_space_release_free_extents(undo->space, n_reserved);
|
fil_space_release_free_extents(undo->space, n_reserved);
|
||||||
|
|
||||||
if (page_no == FIL_NULL) {
|
if (new_block == NULL) {
|
||||||
|
|
||||||
/* No space left */
|
/* No space left */
|
||||||
|
|
||||||
return(FIL_NULL);
|
return(NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
undo->last_page_no = page_no;
|
ut_ad(rw_lock_get_x_lock_count(&new_block->lock) == 1);
|
||||||
|
buf_block_dbg_add_level(new_block, SYNC_TRX_UNDO_PAGE);
|
||||||
|
undo->last_page_no = buf_block_get_page_no(new_block);
|
||||||
|
|
||||||
new_page = trx_undo_page_get(undo->space, undo->zip_size,
|
new_page = buf_block_get_frame(new_block);
|
||||||
page_no, mtr);
|
|
||||||
|
|
||||||
trx_undo_page_init(new_page, undo->type, mtr);
|
trx_undo_page_init(new_page, undo->type, mtr);
|
||||||
|
|
||||||
@ -941,7 +940,7 @@ trx_undo_add_page(
|
|||||||
undo->size++;
|
undo->size++;
|
||||||
rseg->curr_size++;
|
rseg->curr_size++;
|
||||||
|
|
||||||
return(page_no);
|
return(new_block);
|
||||||
}
|
}
|
||||||
|
|
||||||
/********************************************************************//**
|
/********************************************************************//**
|
||||||
|
Reference in New Issue
Block a user