Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
M
mariadb
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
Analytics
Analytics
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Commits
Issue Boards
Open sidebar
Kirill Smelkov
mariadb
Commits
ab20f3b3
Commit
ab20f3b3
authored
Feb 17, 2012
by
kevin.lewis@oracle.com
Browse files
Options
Browse Files
Download
Plain Diff
Merge with mysql-5.5
parents
00939118
a45b4c61
Changes
32
Hide whitespace changes
Inline
Side-by-side
Showing
32 changed files
with
1351 additions
and
582 deletions
+1351
-582
mysql-test/suite/innodb/r/innodb-blob.result
mysql-test/suite/innodb/r/innodb-blob.result
+119
-0
mysql-test/suite/innodb/t/innodb-blob.test
mysql-test/suite/innodb/t/innodb-blob.test
+216
-0
sql/mysqld.cc
sql/mysqld.cc
+4
-0
sql/sys_vars.cc
sql/sys_vars.cc
+1
-0
storage/innobase/btr/btr0btr.c
storage/innobase/btr/btr0btr.c
+101
-49
storage/innobase/btr/btr0cur.c
storage/innobase/btr/btr0cur.c
+173
-78
storage/innobase/fsp/fsp0fsp.c
storage/innobase/fsp/fsp0fsp.c
+234
-169
storage/innobase/ibuf/ibuf0ibuf.c
storage/innobase/ibuf/ibuf0ibuf.c
+22
-26
storage/innobase/include/btr0btr.h
storage/innobase/include/btr0btr.h
+20
-9
storage/innobase/include/btr0cur.h
storage/innobase/include/btr0cur.h
+44
-44
storage/innobase/include/btr0cur.ic
storage/innobase/include/btr0cur.ic
+25
-4
storage/innobase/include/buf0buf.h
storage/innobase/include/buf0buf.h
+27
-2
storage/innobase/include/buf0buf.ic
storage/innobase/include/buf0buf.ic
+4
-17
storage/innobase/include/fsp0fsp.h
storage/innobase/include/fsp0fsp.h
+24
-16
storage/innobase/include/mtr0mtr.h
storage/innobase/include/mtr0mtr.h
+7
-2
storage/innobase/include/mtr0mtr.ic
storage/innobase/include/mtr0mtr.ic
+4
-3
storage/innobase/include/page0page.h
storage/innobase/include/page0page.h
+35
-8
storage/innobase/include/page0page.ic
storage/innobase/include/page0page.ic
+33
-3
storage/innobase/include/sync0sync.h
storage/innobase/include/sync0sync.h
+6
-4
storage/innobase/include/trx0rec.ic
storage/innobase/include/trx0rec.ic
+4
-3
storage/innobase/include/trx0undo.h
storage/innobase/include/trx0undo.h
+7
-6
storage/innobase/mtr/mtr0mtr.c
storage/innobase/mtr/mtr0mtr.c
+1
-1
storage/innobase/page/page0cur.c
storage/innobase/page/page0cur.c
+14
-7
storage/innobase/page/page0page.c
storage/innobase/page/page0page.c
+27
-27
storage/innobase/row/row0ins.c
storage/innobase/row/row0ins.c
+68
-12
storage/innobase/row/row0row.c
storage/innobase/row/row0row.c
+19
-10
storage/innobase/row/row0upd.c
storage/innobase/row/row0upd.c
+46
-18
storage/innobase/sync/sync0rw.c
storage/innobase/sync/sync0rw.c
+6
-4
storage/innobase/sync/sync0sync.c
storage/innobase/sync/sync0sync.c
+11
-5
storage/innobase/trx/trx0rec.c
storage/innobase/trx/trx0rec.c
+20
-17
storage/innobase/trx/trx0sys.c
storage/innobase/trx/trx0sys.c
+8
-16
storage/innobase/trx/trx0undo.c
storage/innobase/trx/trx0undo.c
+21
-22
No files found.
mysql-test/suite/innodb/r/innodb-blob.result
0 → 100644
View file @
ab20f3b3
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;
mysql-test/suite/innodb/t/innodb-blob.test
0 → 100644
View file @
ab20f3b3
# 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
;
sql/mysqld.cc
View file @
ab20f3b3
...
...
@@ -3804,6 +3804,10 @@ a file name for --log-bin-index option", opt_binlog_index_name);
if
(
ha_init_errors
())
DBUG_RETURN
(
1
);
if
(
opt_ignore_builtin_innodb
)
sql_print_warning
(
"ignore-builtin-innodb is deprecated "
"and will be removed in future releases."
);
if
(
plugin_init
(
&
remaining_argc
,
remaining_argv
,
(
opt_noacl
?
PLUGIN_INIT_SKIP_PLUGIN_TABLE
:
0
)
|
(
opt_help
?
PLUGIN_INIT_SKIP_INITIALIZATION
:
0
)))
...
...
sql/sys_vars.cc
View file @
ab20f3b3
...
...
@@ -854,6 +854,7 @@ static Sys_var_charptr Sys_ft_stopword_file(
static
Sys_var_mybool
Sys_ignore_builtin_innodb
(
"ignore_builtin_innodb"
,
"DEPRECATED. This option will be removed in future releases. "
"Disable initialization of builtin InnoDB plugin"
,
READ_ONLY
GLOBAL_VAR
(
opt_ignore_builtin_innodb
),
CMD_LINE
(
OPT_ARG
),
DEFAULT
(
FALSE
));
...
...
storage/innobase/btr/btr0btr.c
View file @
ab20f3b3
...
...
@@ -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.
You should have received a copy of the GNU General Public License along with
this program; if not, write to the Free Software Foundation, Inc.,
59 Temple
Place, Suite 330, Boston, MA 02111-1307
USA
this program; if not, write to the Free Software Foundation, Inc.,
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
that the caller has made the reservation for free extents!
@return new allocated block, x-latched; NULL if out of space */
UNIV_INTERN
@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
*
btr_page_alloc
(
/*===========*/
btr_page_alloc
_low
(
/*===========
====
*/
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: 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
;
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
);
...
...
@@ -962,17 +965,47 @@ btr_page_alloc(
reservation for free extents, and thus we know that a page can
be allocated: */
new_page_no
=
fseg_alloc_free_page_general
(
seg_header
,
hint_page_no
,
file_direction
,
TRUE
,
mtr
);
if
(
new_page_no
==
FIL_NULL
)
{
return
(
fseg_alloc_free_page_general
(
seg_header
,
hint_page_no
,
file_direction
,
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
),
dict_table_zip_size
(
index
->
table
),
new_page_no
,
RW_X_LATCH
,
mtr
);
buf_block_dbg_add_level
(
new_block
,
SYNC_TREE_NODE_NEW
);
new_block
=
btr_page_alloc_low
(
index
,
hint_page_no
,
file_direction
,
level
,
mtr
,
init_mtr
);
if
(
new_block
)
{
buf_block_dbg_add_level
(
new_block
,
SYNC_TREE_NODE_NEW
);
}
return
(
new_block
);
}
...
...
@@ -1099,10 +1132,10 @@ btr_page_free(
buf_block_t
*
block
,
/*!< in: block to be freed, x-latched */
mtr_t
*
mtr
)
/*!< in: mtr */
{
ulint
level
;
level
=
btr_page_get_level
(
buf_block_get_frame
(
block
),
mtr
);
const
page_t
*
page
=
buf_block_get_frame
(
block
);
ulint
level
=
btr_page_get_level
(
page
,
mtr
);
ut_ad
(
fil_page_get_type
(
block
->
frame
)
==
FIL_PAGE_INDEX
);
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
tree root page */
page_no
=
fseg_alloc_free_page
(
buf_block_get_frame
(
ibuf_hdr_block
)
+
IBUF_HEADER
+
IBUF_TREE_SEG_HEADER
,
IBUF_TREE_ROOT_PAGE_NO
,
FSP_UP
,
mtr
);
ut_ad
(
page_no
==
IBUF_TREE_ROOT_PAGE_NO
);
block
=
buf_page_get
(
space
,
zip_size
,
page_no
,
RW_X_LATCH
,
mtr
);
block
=
fseg_alloc_free_page
(
buf_block_get_frame
(
ibuf_hdr_block
)
+
IBUF_HEADER
+
IBUF_TREE_SEG_HEADER
,
IBUF_TREE_ROOT_PAGE_NO
,
FSP_UP
,
mtr
);
ut_ad
(
buf_block_get_page_no
(
block
)
==
IBUF_TREE_ROOT_PAGE_NO
);
}
else
{
#ifdef UNIV_BLOB_DEBUG
if
((
type
&
DICT_CLUSTERED
)
&&
!
index
->
blobs
)
{
...
...
@@ -1833,7 +1862,7 @@ btr_root_raise_and_insert(
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_zip
=
buf_block_get_page_zip
(
new_block
);
ut_a
(
!
new_page_zip
==
!
root_page_zip
);
...
...
@@ -2569,7 +2598,7 @@ func_start:
/* 2. Allocate a new page to the index */
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_zip
=
buf_block_get_page_zip
(
new_block
);
btr_page_create
(
new_block
,
new_page_zip
,
cursor
->
index
,
...
...
@@ -3019,15 +3048,16 @@ btr_node_ptr_delete(
ut_a
(
err
==
DB_SUCCESS
);
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
father page, thus reducing the tree height. */
father page, thus reducing the tree height.
@return father block */
static
void
buf_block_t
*
btr_lift_page_up
(
/*=============*/
dict_index_t
*
index
,
/*!< in: index tree */
...
...
@@ -3144,6 +3174,8 @@ btr_lift_page_up(
}
ut_ad
(
page_validate
(
father_page
,
index
));
ut_ad
(
btr_check_node_ptr
(
index
,
father_block
,
mtr
));
return
(
father_block
);
}
/*************************************************************//**
...
...
@@ -3160,11 +3192,13 @@ UNIV_INTERN
ibool
btr_compress
(
/*=========*/
btr_cur_t
*
cursor
,
/*!< in: cursor on the page to merge or lift;
the page must not be empty: in record delete
use btr_discard_page if the page would become
empty */
mtr_t
*
mtr
)
/*!< in: mtr */
btr_cur_t
*
cursor
,
/*!< in/out: cursor on the page to merge
or lift; the page must not be empty:
when deleting records, use btr_discard_page()
if the page would become empty */
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
;
ulint
space
;
...
...
@@ -3182,6 +3216,7 @@ btr_compress(
ulint
*
offsets
;
ulint
data_size
;
ulint
n_recs
;
ulint
nth_rec
=
0
;
/* remove bogus warning */
ulint
max_ins_size
;
ulint
max_ins_size_reorg
;
...
...
@@ -3209,6 +3244,10 @@ btr_compress(
offsets
=
btr_page_get_father_block
(
NULL
,
heap
,
index
,
block
,
mtr
,
&
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
the locks */
...
...
@@ -3235,9 +3274,9 @@ btr_compress(
}
else
{
/* The page is the only one on the level, lift the records
to the father */
btr_lift_page_up
(
index
,
block
,
mtr
);
me
m_heap_free
(
heap
);
return
(
TRUE
)
;
me
rge_block
=
btr_lift_page_up
(
index
,
block
,
mtr
);
goto
func_exit
;
}
n_recs
=
page_get_n_recs
(
page
);
...
...
@@ -3319,6 +3358,10 @@ err_exit:
btr_node_ptr_delete
(
index
,
block
,
mtr
);
lock_update_merge_left
(
merge_block
,
orig_pred
,
block
);
if
(
adjust
)
{
nth_rec
+=
page_rec_get_n_recs_before
(
orig_pred
);
}
}
else
{
rec_t
*
orig_succ
;
#ifdef UNIV_BTR_DEBUG
...
...
@@ -3383,7 +3426,6 @@ err_exit:
}
btr_blob_dbg_remove
(
page
,
index
,
"btr_compress"
);
mem_heap_free
(
heap
);
if
(
!
dict_index_is_clust
(
index
)
&&
page_is_leaf
(
merge_page
))
{
/* Update the free bits of the B-tree page in the
...
...
@@ -3435,6 +3477,16 @@ err_exit:
btr_page_free
(
index
,
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
);
}
...
...
storage/innobase/btr/btr0cur.c
View file @
ab20f3b3
...
...
@@ -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.
You should have received a copy of the GNU General Public License along with
this program; if not, write to the Free Software Foundation, Inc.,
59 Temple
Place, Suite 330, Boston, MA 02111-1307
USA
this program; if not, write to the Free Software Foundation, Inc.,
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
);
/* 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
,
rec_offs_size
(
offsets
),
FALSE
,
mtr
))
{
return
(
DB_ZIP_OVERFLOW
);
...
...
@@ -2051,7 +2051,7 @@ any_extern:
ut_a
(
!
page_zip
||
page_zip_validate
(
page_zip
,
page
));
#endif
/* UNIV_ZIP_DEBUG */
if
(
UNIV_LIKELY_NULL
(
page_zip
)
if
(
page_zip
&&
!
btr_cur_update_alloc_zip
(
page_zip
,
block
,
index
,
new_rec_size
,
TRUE
,
mtr
))
{
err
=
DB_ZIP_OVERFLOW
;
...
...
@@ -2209,7 +2209,9 @@ btr_cur_pessimistic_update(
/*=======================*/
ulint
flags
,
/*!< in: undo logging, locking, and rollback
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 */
big_rec_t
**
big_rec
,
/*!< out: big rec vector whose fields have to
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 */
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
);
if
(
UNIV_LIKELY_NULL
(
page_zip
)
)
{
if
(
page_zip
)
{
ut_ad
(
page_is_comp
(
page
));
if
(
page_zip_rec_needs_ext
(
rec_get_converted_size
(
index
,
new_entry
,
n_ext
),
...
...
@@ -2371,6 +2373,10 @@ make_external:
err
=
DB_TOO_BIG_RECORD
;
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,
...
...
@@ -2398,6 +2404,8 @@ make_external:
rec
=
btr_cur_insert_if_possible
(
cursor
,
new_entry
,
n_ext
,
mtr
);
if
(
rec
)
{
page_cursor
->
rec
=
rec
;
lock_rec_restore_from_page_infimum
(
btr_cur_get_block
(
cursor
),
rec
,
block
);
...
...
@@ -2411,7 +2419,10 @@ make_external:
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
)
&&
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
record on its page? */
was_first
=
page_cur_is_before_first
(
page_cursor
);
...
...
@@ -2446,6 +2472,7 @@ make_external:
ut_a
(
rec
);
ut_a
(
err
==
DB_SUCCESS
);
ut_a
(
dummy_big_rec
==
NULL
);
page_cursor
->
rec
=
rec
;
if
(
dict_index_is_sec_or_ibuf
(
index
))
{
/* Update PAGE_MAX_TRX_ID in the index page header.
...
...
@@ -2880,10 +2907,12 @@ UNIV_INTERN
ibool
btr_cur_compress_if_useful
(
/*=======================*/
btr_cur_t
*
cursor
,
/*!< in: cursor on the page to compress;
cursor does not stay valid if compression
occurs */
mtr_t
*
mtr
)
/*!< in: mtr */
btr_cur_t
*
cursor
,
/*!< in/out: cursor on the page to compress;
cursor does not stay valid if !adjust and
compression occurs */
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
,
dict_index_get_lock
(
btr_cur_get_index
(
cursor
)),
...
...
@@ -2892,7 +2921,7 @@ btr_cur_compress_if_useful(
MTR_MEMO_PAGE_X_FIX
));
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
);
if
(
ret
==
FALSE
)
{
ret
=
btr_cur_compress_if_useful
(
cursor
,
mtr
);
ret
=
btr_cur_compress_if_useful
(
cursor
,
FALSE
,
mtr
);
}
if
(
n_extents
>
0
)
{
...
...
@@ -3870,10 +3899,10 @@ btr_cur_set_ownership_of_extern_field(
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
);
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_1BYTE
,
mtr
);
...
...
@@ -4106,9 +4135,9 @@ The fields are stored on pages allocated from leaf node
file segment of the index tree.
@return DB_SUCCESS or DB_OUT_OF_FILE_SPACE */
UNIV_INTERN
ulint
btr_store_big_rec_extern_fields
_func
(
/*============================
=====
*/
enum
db_err
btr_store_big_rec_extern_fields
(
/*============================*/
dict_index_t
*
index
,
/*!< in: index of rec; the index tree
MUST be X-latched */
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
will not correspond to rec when
this function returns */
#ifdef UNIV_DEBUG
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
const
big_rec_t
*
big_rec_vec
,
/*!< in: vector containing fields
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
;
byte
*
field_ref
;
ulint
extern_len
;
ulint
store_len
;
ulint
page_no
;
ulint
space_id
;
ulint
zip_size
;
ulint
prev_page_no
;
ulint
hint_page_no
;
ulint
i
;
mtr_t
mtr
;
mem_heap_t
*
heap
=
NULL
;
ulint
rec_page_no
;
byte
*
field_ref
;
ulint
extern_len
;
ulint
store_len
;
ulint
page_no
;
ulint
space_id
;
ulint
zip_size
;
ulint
prev_page_no
;
ulint
hint_page_no
;
ulint
i
;
mtr_t
mtr
;
mtr_t
*
alloc_mtr
;
mem_heap_t
*
heap
=
NULL
;
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_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
));
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_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
);
ut_a
(
fil_page_get_type
(
page_align
(
rec
))
==
FIL_PAGE_INDEX
);
if
(
UNIV_LIKELY_NULL
(
page_zip
)
)
{
if
(
page_zip
)
{
int
err
;
/* Zlib deflate needs 128 kilobytes for the default
...
...
@@ -4177,6 +4205,42 @@ btr_store_big_rec_extern_fields_func(
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
/* All pointers to externally stored columns in the record
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,
or the BLOB must be inherited, or the BLOB pointer
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
)
||
!
memcmp
(
field_ref
,
field_ref_zero
,
BTR_EXTERN_FIELD_REF_SIZE
));
...
...
@@ -4216,7 +4280,7 @@ btr_store_big_rec_extern_fields_func(
prev_page_no
=
FIL_NULL
;
if
(
UNIV_LIKELY_NULL
(
page_zip
)
)
{
if
(
page_zip
)
{
int
err
=
deflateReset
(
&
c_stream
);
ut_a
(
err
==
Z_OK
);
...
...
@@ -4236,18 +4300,24 @@ btr_store_big_rec_extern_fields_func(
hint_page_no
=
prev_page_no
+
1
;
}
alloc_another:
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
))
{
mtr_commit
(
&
mtr
);
error
=
DB_OUT_OF_FILE_SPACE
;
goto
func_exit
;
}
if
(
UNIV_LIKELY_NULL
(
page_zip
))
{
deflateEnd
(
&
c_stream
);
mem_heap_free
(
heap
);
}
return
(
DB_OUT_OF_FILE_SPACE
);
if
(
rw_lock_get_x_lock_count
(
&
block
->
lock
)
>
1
)
{
/* This page must have been freed in
btr_mtr previously. Put it aside, and
allocate another page for the BLOB data. */
ut_ad
(
alloc_mtr
==
btr_mtr
);
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
);
...
...
@@ -4264,7 +4334,7 @@ btr_store_big_rec_extern_fields_func(
SYNC_EXTERN_STORAGE
);
prev_page
=
buf_block_get_frame
(
prev_block
);
if
(
UNIV_LIKELY_NULL
(
page_zip
)
)
{
if
(
page_zip
)
{
mlog_write_ulint
(
prev_page
+
FIL_PAGE_NEXT
,
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
;
page_zip_des_t
*
blob_page_zip
;
...
...
@@ -4364,11 +4434,15 @@ btr_store_big_rec_extern_fields_func(
goto
next_zip_page
;
}
rec_block
=
buf_page_get
(
space_id
,
zip_size
,
rec_page_no
,
RW_X_LATCH
,
&
mtr
);
buf_block_dbg_add_level
(
rec_block
,
SYNC_NO_ORDER_CHECK
);
if
(
alloc_mtr
==
&
mtr
)
{
rec_block
=
buf_page_get
(
space_id
,
zip_size
,
rec_page_no
,
RW_X_LATCH
,
&
mtr
);
buf_block_dbg_add_level
(
rec_block
,
SYNC_NO_ORDER_CHECK
);
}
if
(
err
==
Z_STREAM_END
)
{
mach_write_to_4
(
field_ref
...
...
@@ -4402,7 +4476,8 @@ btr_store_big_rec_extern_fields_func(
page_zip_write_blob_ptr
(
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:
prev_page_no
=
page_no
;
...
...
@@ -4447,19 +4522,23 @@ next_zip_page:
extern_len
-=
store_len
;
rec_block
=
buf_page_get
(
space_id
,
zip_size
,
rec_page_no
,
RW_X_LATCH
,
&
mtr
);
buf_block_dbg_add_level
(
rec_block
,
SYNC_NO_ORDER_CHECK
);
if
(
alloc_mtr
==
&
mtr
)
{
rec_block
=
buf_page_get
(
space_id
,
zip_size
,
rec_page_no
,
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_4BYTES
,
&
mtr
);
MLOG_4BYTES
,
alloc_
mtr
);
mlog_write_ulint
(
field_ref
+
BTR_EXTERN_LEN
+
4
,
big_rec_vec
->
fields
[
i
].
len
-
extern_len
,
MLOG_4BYTES
,
&
mtr
);
MLOG_4BYTES
,
alloc_
mtr
);
if
(
prev_page_no
==
FIL_NULL
)
{
btr_blob_dbg_add_blob
(
...
...
@@ -4469,18 +4548,19 @@ next_zip_page:
mlog_write_ulint
(
field_ref
+
BTR_EXTERN_SPACE_ID
,
space_id
,
MLOG_4BYTES
,
&
mtr
);
space_id
,
MLOG_4BYTES
,
alloc_
mtr
);
mlog_write_ulint
(
field_ref
+
BTR_EXTERN_PAGE_NO
,
page_no
,
MLOG_4BYTES
,
&
mtr
);
page_no
,
MLOG_4BYTES
,
alloc_
mtr
);
mlog_write_ulint
(
field_ref
+
BTR_EXTERN_OFFSET
,
FIL_PAGE_DATA
,
MLOG_4BYTES
,
&
mtr
);
MLOG_4BYTES
,
alloc_mtr
);
}
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
);
}
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
);
}
...
...
@@ -4516,7 +4611,7 @@ next_zip_page:
ut_a
(
!
(
field_ref
[
BTR_EXTERN_LEN
]
&
BTR_EXTERN_OWNER_FLAG
));
}
#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
);
if
(
UNIV_LIKELY
(
page_zip
!=
NULL
)
)
{
if
(
page_zip
)
{
mach_write_to_4
(
field_ref
+
BTR_EXTERN_PAGE_NO
,
next_page_no
);
mach_write_to_4
(
field_ref
+
BTR_EXTERN_LEN
+
4
,
...
...
storage/innobase/fsp/fsp0fsp.c
View file @
ab20f3b3
/*****************************************************************************
Copyright (c) 1995, 201
1
, Oracle and/or its affiliates. All Rights Reserved.
Copyright (c) 1995, 201
2
, Oracle and/or its affiliates. All Rights Reserved.
This program is free software; you can redistribute it and/or modify it under
the terms of the GNU General Public License as published by the Free Software
...
...
@@ -250,28 +250,38 @@ fsp_fill_free_list(
descriptor page and ibuf bitmap page;
then we do not allocate more extents */
ulint
space
,
/*!< in: space */
fsp_header_t
*
header
,
/*!< in: space header */
mtr_t
*
mtr
);
/*!< in: mtr */
fsp_header_t
*
header
,
/*!< in/out: space header */
mtr_t
*
mtr
)
/*!< in/out: mini-transaction */
__attribute__
((
nonnull
));
/**********************************************************************//**
Allocates a single free page from a segment. This function implements
the intelligent allocation strategy which tries to minimize file space
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
ulint
buf_block_t
*
fseg_alloc_free_page_low
(
/*=====================*/
ulint
space
,
/*!< in: space */
ulint
zip_size
,
/*!< in: compressed page size in bytes
or 0 for uncompressed pages */
fseg_inode_t
*
seg_inode
,
/*!< in: segment inode */
ulint
hint
,
/*!< in: hint of which page would be desirable */
fseg_inode_t
*
seg_inode
,
/*!< in/out: segment inode */
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 */
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 */
/**********************************************************************//**
...
...
@@ -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.
@return pointer to the extent descriptor, NULL if the page does not
exist in the space or if the offset exceeds the free limit */
UNIV_INLINE
UNIV_INLINE
__attribute__
((
nonnull
,
warn_unused_result
))
xdes_t
*
xdes_get_descriptor_with_space_hdr
(
/*===============================*/
fsp_header_t
*
sp_header
,
/*!< in/out: space header, x-latched */
ulint
space
,
/*!< in: space id */
ulint
offset
,
/*!< in: page offset;
if equal to the free limit,
we try to add new extents to
the space free list */
mtr_t
*
mtr
)
/*!< in: mtr handle */
fsp_header_t
*
sp_header
,
/*!< in/out: space header, x-latched
in mtr */
ulint
space
,
/*!< in: space id */
ulint
offset
,
/*!< in: page offset; if equal
to the free limit, we try to
add new extents to the space
free list */
mtr_t
*
mtr
)
/*!< in/out: mini-transaction */
{
ulint
limit
;
ulint
size
;
...
...
@@ -657,11 +668,9 @@ xdes_get_descriptor_with_space_hdr(
ulint
descr_page_no
;
page_t
*
descr_page
;
ut_ad
(
mtr
);
ut_ad
(
mtr_memo_contains
(
mtr
,
fil_space_get_latch
(
space
,
NULL
),
MTR_MEMO_X_LOCK
));
ut_ad
(
mtr_memo_contains_page
(
mtr
,
sp_header
,
MTR_MEMO_PAGE_S_FIX
)
||
mtr_memo_contains_page
(
mtr
,
sp_header
,
MTR_MEMO_PAGE_X_FIX
));
ut_ad
(
mtr_memo_contains_page
(
mtr
,
sp_header
,
MTR_MEMO_PAGE_X_FIX
));
ut_ad
(
page_offset
(
sp_header
)
==
FSP_HEADER_OFFSET
);
/* Read free limit and space size */
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.
@return pointer to the extent descriptor, NULL if the page does not
exist in the space or if the offset exceeds the free limit */
static
static
__attribute__
((
nonnull
,
warn_unused_result
))
xdes_t
*
xdes_get_descriptor
(
/*================*/
...
...
@@ -720,7 +729,7 @@ xdes_get_descriptor(
or 0 for uncompressed pages */
ulint
offset
,
/*!< in: page offset; if equal to the free limit,
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
;
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
data file.
@return TRUE if success */
static
static
__attribute__
((
nonnull
,
warn_unused_result
))
ibool
fsp_try_extend_data_file_with_pages
(
/*================================*/
ulint
space
,
/*!< in: space */
ulint
page_no
,
/*!< in: page number */
fsp_header_t
*
header
,
/*!< in: space header */
mtr_t
*
mtr
)
/*!< in
: mtr
*/
fsp_header_t
*
header
,
/*!< in
/out
: space header */
mtr_t
*
mtr
)
/*!< in
/out: mini-transaction
*/
{
ibool
success
;
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.
@return FALSE if not auto-extending */
static
static
__attribute__
((
nonnull
))
ibool
fsp_try_extend_data_file
(
/*=====================*/
...
...
@@ -1140,8 +1149,8 @@ fsp_try_extend_data_file(
the actual file size rounded down to
megabyte */
ulint
space
,
/*!< in: space */
fsp_header_t
*
header
,
/*!< in: space header */
mtr_t
*
mtr
)
/*!< in
: mtr
*/
fsp_header_t
*
header
,
/*!< in
/out
: space header */
mtr_t
*
mtr
)
/*!< in
/out: mini-transaction
*/
{
ulint
size
;
ulint
zip_size
;
...
...
@@ -1277,7 +1286,7 @@ fsp_fill_free_list(
then we do not allocate more extents */
ulint
space
,
/*!< in: space */
fsp_header_t
*
header
,
/*!< in/out: space header */
mtr_t
*
mtr
)
/*!< in
: mtr
*/
mtr_t
*
mtr
)
/*!< in
/out: mini-transaction
*/
{
ulint
limit
;
ulint
size
;
...
...
@@ -1476,29 +1485,120 @@ fsp_alloc_free_extent(
}
/**********************************************************************//**
Allocates a single free page from a space. The page is marked as used.
@return the page offset, FIL_NULL if no page could be allocated */
Allocates a single free page from a space. */
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
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
(
/*================*/
ulint
space
,
/*!< in: space id */
ulint
zip_size
,
/*!< in: compressed page size in bytes
or 0 for uncompressed pages */
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
;
fil_addr_t
first
;
xdes_t
*
descr
;
buf_block_t
*
block
;
ulint
free
;
ulint
frag_n_used
;
ulint
page_no
;
ulint
space_size
;
ibool
success
;
ut_ad
(
mtr
);
ut_ad
(
init_mtr
);
header
=
fsp_get_space_header
(
space
,
zip_size
,
mtr
);
...
...
@@ -1525,7 +1625,7 @@ fsp_alloc_free_page(
if
(
descr
==
NULL
)
{
/* No free space left */
return
(
FIL_
NULL
);
return
(
NULL
);
}
xdes_set_state
(
descr
,
XDES_FREE_FRAG
,
mtr
);
...
...
@@ -1570,50 +1670,18 @@ fsp_alloc_free_page(
" space size %lu. Page no %lu.
\n
"
,
(
ulong
)
space
,
(
ulong
)
space_size
,
(
ulong
)
page_no
);
return
(
FIL_
NULL
);
return
(
NULL
);
}
success
=
fsp_try_extend_data_file_with_pages
(
space
,
page_no
,
header
,
mtr
);
if
(
!
success
)
{
if
(
!
fsp_try_extend_data_file_with_pages
(
space
,
page_no
,
header
,
mtr
))
{
/* 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 */
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
);
return
(
fsp_page_create
(
space
,
zip_size
,
page_no
,
mtr
,
init_mtr
));
}
/**********************************************************************//**
...
...
@@ -1652,6 +1720,9 @@ fsp_free_page(
fputs
(
"InnoDB: Dump of descriptor: "
,
stderr
);
ut_print_buf
(
stderr
,
((
byte
*
)
descr
)
-
50
,
200
);
putc
(
'\n'
,
stderr
);
/* Crash in debug version, so that we get a core dump
of this corruption. */
ut_ad
(
0
);
if
(
state
==
XDES_FREE
)
{
/* We put here some fault tolerance: if the page
...
...
@@ -1670,6 +1741,9 @@ fsp_free_page(
"InnoDB: Dump of descriptor: "
,
(
ulong
)
page
);
ut_print_buf
(
stderr
,
((
byte
*
)
descr
)
-
50
,
200
);
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
is already free, return without doing anything! */
...
...
@@ -1704,6 +1778,8 @@ fsp_free_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
;
buf_block_t
*
block
;
page_t
*
page
;
ulint
page_no
;
ulint
space
;
ulint
zip_size
;
ulint
i
;
...
...
@@ -1847,15 +1922,15 @@ fsp_alloc_seg_inode_page(
zip_size
=
dict_table_flags_to_zip_size
(
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
);
}
block
=
buf_page_get
(
space
,
zip_size
,
page_no
,
RW_X_LATCH
,
mtr
);
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
;
...
...
@@ -2258,19 +2333,20 @@ fseg_create_general(
}
if
(
page
==
0
)
{
page
=
fseg_alloc_free_page_low
(
space
,
zip_size
,
inode
,
0
,
FSP_UP
,
mtr
);
block
=
fseg_alloc_free_page_low
(
space
,
zip_size
,
inode
,
0
,
FSP_UP
,
mtr
,
mtr
);
if
(
page
==
FIL_
NULL
)
{
if
(
block
==
NULL
)
{
fsp_free_seg_inode
(
space
,
zip_size
,
inode
,
mtr
);
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
);
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
);
}
...
...
@@ -2447,8 +2523,10 @@ fseg_fill_free_list(
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
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
if could not 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
xdes_t
*
fseg_alloc_free_extent
(
...
...
@@ -2500,22 +2578,30 @@ fseg_alloc_free_extent(
Allocates a single free page from a segment. This function implements
the intelligent allocation strategy which tries to minimize file space
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
ulint
buf_block_t
*
fseg_alloc_free_page_low
(
/*=====================*/
ulint
space
,
/*!< in: space */
ulint
zip_size
,
/*!< in: compressed page size in bytes
or 0 for uncompressed pages */
fseg_inode_t
*
seg_inode
,
/*!< in: segment inode */
ulint
hint
,
/*!< in: hint of which page would be desirable */
fseg_inode_t
*
seg_inode
,
/*!< in/out: segment inode */
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 */
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
;
ulint
space_size
;
...
...
@@ -2526,7 +2612,6 @@ fseg_alloc_free_page_low(
ulint
ret_page
;
/*!< the allocated page offset, FIL_NULL
if could not be allocated */
xdes_t
*
ret_descr
;
/*!< the extent of the allocated page */
ibool
frag_page_allocated
=
FALSE
;
ibool
success
;
ulint
n
;
...
...
@@ -2548,6 +2633,7 @@ fseg_alloc_free_page_low(
if
(
descr
==
NULL
)
{
/* Hint outside space or too high above free limit: reset
hint */
/* The file space header page is always allocated. */
hint
=
0
;
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
&&
(
xdes_get_bit
(
descr
,
XDES_FREE_BIT
,
hint
%
FSP_EXTENT_SIZE
,
mtr
)
==
TRUE
))
{
take_hinted_page:
/* 1. We can take the hinted page
=================================*/
ret_descr
=
descr
;
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
)
&&
((
reserved
-
used
)
<
reserved
/
FSEG_FILLFACTOR
)
&&
(
used
>=
FSEG_FRAG_LIMIT
)
)
{
}
else
if
(
xdes_get_state
(
descr
,
mtr
)
==
XDES_FREE
&&
reserved
-
used
<
reserved
/
FSEG_FILLFACTOR
&&
used
>=
FSEG_FRAG_LIMIT
)
{
/* 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 */
fseg_fill_free_list
(
seg_inode
,
space
,
zip_size
,
hint
+
FSP_EXTENT_SIZE
,
mtr
);
ret_page
=
hint
;
goto
take_hinted_page
;
/*-----------------------------------------------------------*/
}
else
if
((
direction
!=
FSP_NO_DIR
)
&&
((
reserved
-
used
)
<
reserved
/
FSEG_FILLFACTOR
)
...
...
@@ -2632,7 +2722,7 @@ fseg_alloc_free_page_low(
first
=
flst_get_first
(
seg_inode
+
FSEG_FREE
,
mtr
);
}
else
{
ut_error
;
return
(
FIL_
NULL
);
return
(
NULL
);
}
ret_descr
=
xdes_lst_get_descriptor
(
space
,
zip_size
,
...
...
@@ -2644,20 +2734,23 @@ fseg_alloc_free_page_low(
}
else
if
(
used
<
FSEG_FRAG_LIMIT
)
{
/* 6. We allocate an individual page from the space
===================================================*/
ret_page
=
fsp_alloc_free_page
(
space
,
zip_size
,
hint
,
mtr
);
ret_descr
=
NULL
;
buf_block_t
*
block
=
fsp_alloc_free_page
(
space
,
zip_size
,
hint
,
mtr
,
init_mtr
)
;
frag_page_allocated
=
TRUE
;
if
(
ret_page
!=
FIL_NULL
)
{
if
(
block
!=
NULL
)
{
/* Put the page in the fragment page array of the
segment */
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
,
mtr
);
fseg_set_nth_frag_page_no
(
seg_inode
,
n
,
buf_block_get_page_no
(
block
),
mtr
);
}
/* fsp_alloc_free_page() invoked fsp_init_file_page()
already. */
return
(
block
);
/*-----------------------------------------------------------*/
}
else
{
/* 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
)
{
/* Page could not be allocated */
return
(
FIL_
NULL
);
return
(
NULL
);
}
if
(
space
!=
0
)
{
...
...
@@ -2693,38 +2786,22 @@ fseg_alloc_free_page_low(
" the space size %lu. Page no %lu.
\n
"
,
(
ulong
)
space
,
(
ulong
)
space_size
,
(
ulong
)
ret_page
);
return
(
FIL_
NULL
);
return
(
NULL
);
}
success
=
fsp_try_extend_data_file_with_pages
(
space
,
ret_page
,
space_header
,
mtr
);
if
(
!
success
)
{
/* No disk space left */
return
(
FIL_
NULL
);
return
(
NULL
);
}
}
}
if
(
!
frag_page_allocated
)
{
/* Initialize the allocated page to buffer pool, so that it
can be obtained immediately with buf_page_get without need
for a disk read */
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
);
got_hinted_page:
/* ret_descr == NULL if the block was allocated from free_frag
(XDES_FREE_FRAG) */
if
(
ret_descr
!=
NULL
)
{
/* At this point we know the extent and the page offset.
The extent is still in the appropriate list (FSEG_NOT_FULL
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
);
}
buf_reset_check_index_page_at_flush
(
space
,
ret_page
);
return
(
ret_page
);
return
(
fsp_page_create
(
space
,
dict_table_flags_to_zip_size
(
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
the intelligent allocation strategy which tries to minimize file space
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
ulint
buf_block_t
*
fseg_alloc_free_page_general
(
/*=========================*/
fseg_header_t
*
seg_header
,
/*!< in: segment header */
ulint
hint
,
/*!< in: hint of which page would be desirable */
fseg_header_t
*
seg_header
,
/*!< in/out: 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
...
...
@@ -2763,15 +2846,18 @@ fseg_alloc_free_page_general(
with fsp_reserve_free_extents, then there
is no need to do the check for this individual
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
;
ulint
space
;
ulint
flags
;
ulint
zip_size
;
rw_lock_t
*
latch
;
ibool
success
;
ulint
page_no
;
buf_block_t
*
block
;
ulint
n_reserved
;
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
);
if
(
!
has_done_reservation
)
{
success
=
fsp_reserve_free_extents
(
&
n_reserved
,
space
,
2
,
FSP_NORMAL
,
mtr
);
if
(
!
success
)
{
return
(
FIL_NULL
);
}
if
(
!
has_done_reservation
&&
!
fsp_reserve_free_extents
(
&
n_reserved
,
space
,
2
,
FSP_NORMAL
,
mtr
))
{
return
(
NULL
);
}
page_no
=
fseg_alloc_free_page_low
(
space
,
zip_size
,
inode
,
hint
,
direction
,
mtr
);
block
=
fseg_alloc_free_page_low
(
space
,
zip_size
,
inode
,
hint
,
direction
,
mtr
,
init_mtr
);
if
(
!
has_done_reservation
)
{
fil_space_release_free_extents
(
space
,
n_reserved
);
}
return
(
page_no
);
}
/**********************************************************************//**
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
));
return
(
block
);
}
/**********************************************************************//**
...
...
@@ -3344,6 +3407,8 @@ crash:
descr
+
XDES_FLST_NODE
,
mtr
);
fsp_free_extent
(
space
,
zip_size
,
page
,
mtr
);
}
mtr
->
n_freed_pages
++
;
}
/**********************************************************************//**
...
...
storage/innobase/ibuf/ibuf0ibuf.c
View file @
ab20f3b3
...
...
@@ -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.
You should have received a copy of the GNU General Public License along with
this program; if not, write to the Free Software Foundation, Inc.,
59 Temple
Place, Suite 330, Boston, MA 02111-1307
USA
this program; if not, write to the Free Software Foundation, Inc.,
51 Franklin Street, Suite 500, Boston, MA 02110-1335
USA
*****************************************************************************/
...
...
@@ -2180,14 +2180,14 @@ ibool
ibuf_add_free_page
(
void
)
/*====================*/
{
mtr_t
mtr
;
page_t
*
header_page
;
ulint
flags
;
ulint
zip_size
;
ulint
page_no
;
page_t
*
page
;
page_t
*
root
;
page_t
*
bitmap_page
;
mtr_t
mtr
;
page_t
*
header_page
;
ulint
flags
;
ulint
zip_size
;
buf_block_t
*
block
;
page_t
*
page
;
page_t
*
root
;
page_t
*
bitmap_page
;
mtr_start
(
&
mtr
);
...
...
@@ -2208,28 +2208,23 @@ ibuf_add_free_page(void)
of a deadlock. This is the reason why we created a special ibuf
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
,
&
mtr
);
if
(
UNIV_UNLIKELY
(
page_no
==
FIL_NULL
)
)
{
if
(
block
==
NULL
)
{
mtr_commit
(
&
mtr
);
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
);
ut_ad
(
rw_lock_get_x_lock_count
(
&
block
->
lock
)
==
1
);
ibuf_enter
(
&
mtr
);
mutex_enter
(
&
ibuf_mutex
);
root
=
ibuf_tree_root_get
(
&
mtr
);
page
=
buf_block_get_frame
(
block
);
}
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 */
...
...
@@ -2246,12 +2241,13 @@ ibuf_add_free_page(void)
(level 2 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
);
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
);
...
...
storage/innobase/include/btr0btr.h
View file @
ab20f3b3
...
...
@@ -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.
You should have received a copy of the GNU General Public License along with
this program; if not, write to the Free Software Foundation, Inc.,
59 Temple
Place, Suite 330, Boston, MA 02111-1307
USA
this program; if not, write to the Free Software Foundation, Inc.,
51 Franklin Street, Suite 500, Boston, MA 02110-1335
USA
*****************************************************************************/
...
...
@@ -519,11 +519,14 @@ UNIV_INTERN
ibool
btr_compress
(
/*=========*/
btr_cur_t
*
cursor
,
/*!< in: cursor on the page to merge or lift;
the page must not be empty: in record delete
use btr_discard_page if the page would become
empty */
mtr_t
*
mtr
);
/*!< in: mtr */
btr_cur_t
*
cursor
,
/*!< in/out: cursor on the page to merge
or lift; the page must not be empty:
when deleting records, use btr_discard_page()
if the page would become empty */
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
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
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
buf_block_t
*
btr_page_alloc
(
...
...
@@ -585,7 +591,12 @@ btr_page_alloc(
page split is made */
ulint
level
,
/*!< in: level where the page is placed
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
storage pages because the page must contain info on its level. */
...
...
storage/innobase/include/btr0cur.h
View file @
ab20f3b3
/*****************************************************************************
Copyright (c) 1994, 201
0, Innobase Oy
. All Rights Reserved.
Copyright (c) 1994, 201
2, Oracle and/or its affiliates
. All Rights Reserved.
This program is free software; you can redistribute it and/or modify it under
the terms of the GNU General Public License as published by the Free Software
...
...
@@ -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.
You should have received a copy of the GNU General Public License along with
this program; if not, write to the Free Software Foundation, Inc.,
59 Temple
Place, Suite 330, Boston, MA 02111-1307
USA
this program; if not, write to the Free Software Foundation, Inc.,
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_KEEP_SYS_FLAG 4
/* sys fields will be found from the
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
#include "que0types.h"
...
...
@@ -310,7 +313,9 @@ btr_cur_pessimistic_update(
/*=======================*/
ulint
flags
,
/*!< in: undo logging, locking, and rollback
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 */
big_rec_t
**
big_rec
,
/*!< out: big rec vector whose fields have to
be stored externally by the caller, or NULL */
...
...
@@ -364,10 +369,13 @@ UNIV_INTERN
ibool
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
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
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 */
mtr_t
*
mtr
)
/*!< in/out: mini-transaction */
__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
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.
@return DB_SUCCESS or DB_OUT_OF_FILE_SPACE */
UNIV_INTERN
ulint
btr_store_big_rec_extern_fields
_func
(
/*============================
=====
*/
enum
db_err
btr_store_big_rec_extern_fields
(
/*============================*/
dict_index_t
*
index
,
/*!< in: index of rec; the index tree
MUST be X-latched */
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);
the "external storage" flags in offsets
will not correspond to rec when
this function returns */
#ifdef UNIV_DEBUG
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
const
big_rec_t
*
big_rec_vec
,
/*!< in: vector containing fields
to be stored externally */
__attribute__
((
nonnull
));
/** 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.
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
mtr_t
*
btr_mtr
,
/*!< in: mtr containing the
latches to the clustered index */
enum
blob_op
op
)
/*! in: operation code */
__attribute__
((
nonnull
,
warn_unused_result
));
/*******************************************************************//**
Frees the space in an externally stored field to the file space
...
...
storage/innobase/include/btr0cur.ic
View file @
ab20f3b3
/*****************************************************************************
Copyright (c) 1994, 20
09, Innobase Oy
. All Rights Reserved.
Copyright (c) 1994, 20
12, Oracle and/or its affiliates
. All Rights Reserved.
This program is free software; you can redistribute it and/or modify it under
the terms of the GNU General Public License as published by the Free Software
...
...
@@ -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.
You should have received a copy of the GNU General Public License along with
this program; if not, write to the Free Software Foundation, Inc.,
59 Temple
Place, Suite 330, Boston, MA 02111-1307
USA
this program; if not, write to the Free Software Foundation, Inc.,
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 */
mtr_t* mtr) /*!< in: mtr */
{
page_t*
page;
const page_t*
page;
ut_ad(mtr_memo_contains(mtr, btr_cur_get_block(cursor),
MTR_MEMO_PAGE_X_FIX));
...
...
@@ -197,4 +197,25 @@ btr_cur_can_delete_without_compress(
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 */
storage/innobase/include/buf0buf.h
View file @
ab20f3b3
...
...
@@ -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.
You should have received a copy of the GNU General Public License along with
this program; if not, write to the Free Software Foundation, Inc.,
59 Temple
Place, Suite 330, Boston, MA 02111-1307
USA
this program; if not, write to the Free Software Foundation, Inc.,
51 Franklin Street, Suite 500, Boston, MA 02110-1335
USA
*****************************************************************************/
...
...
@@ -596,6 +596,31 @@ buf_block_get_modify_clock(
#else
/* !UNIV_HOTBACKUP */
# define buf_block_modify_clock_inc(block) ((void) 0)
#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
to a file. Note that we must be careful to calculate the same value
...
...
storage/innobase/include/buf0buf.ic
View file @
ab20f3b3
/*****************************************************************************
Copyright (c) 1995, 201
0, Innobase Oy
. All Rights Reserved.
Copyright (c) 1995, 201
2, Oracle and/or its affiliates
. All Rights Reserved.
Copyright (c) 2008, Google Inc.
Portions of this file contain modifications contributed and copyrighted by
...
...
@@ -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.
You should have received a copy of the GNU General Public License along with
this program; if not, write to the Free Software Foundation, Inc.,
59 Temple
Place, Suite 330, Boston, MA 02111-1307
USA
this program; if not, write to the Free Software Foundation, Inc.,
51 Franklin Street, Suite 500, Boston, MA 02110-1335
USA
*****************************************************************************/
...
...
@@ -988,19 +988,6 @@ buf_block_buf_fix_inc_func(
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. */
...
...
@@ -1251,7 +1238,7 @@ buf_block_dbg_add_level(
where we have acquired latch */
ulint level) /*!< in: latching order level */
{
sync_thread_add_level(&block->lock, level);
sync_thread_add_level(&block->lock, level
, FALSE
);
}
#endif /* UNIV_SYNC_DEBUG */
/********************************************************************//**
...
...
storage/innobase/include/fsp0fsp.h
View file @
ab20f3b3
/*****************************************************************************
Copyright (c) 1995, 201
1
, Oracle and/or its affiliates. All Rights Reserved.
Copyright (c) 1995, 201
2
, Oracle and/or its affiliates. All Rights Reserved.
This program is free software; you can redistribute it and/or modify it under
the terms of the GNU General Public License as published by the Free Software
...
...
@@ -260,30 +260,33 @@ fseg_n_reserved_pages(
Allocates a single free page from a segment. This function implements
the intelligent allocation strategy which tries to minimize
file space fragmentation.
@return the 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
@param[in/out] seg_header segment header
@param[in] hint hint of which page would be desirable
@param[in] direction 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 */
FSP_UP, FSP_NO_DIR
@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
the intelligent allocation strategy which tries to minimize file space
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
ulint
buf_block_t
*
fseg_alloc_free_page_general
(
/*=========================*/
fseg_header_t
*
seg_header
,
/*!< in: segment header */
ulint
hint
,
/*!< in: hint of which page would be desirable */
fseg_header_t
*
seg_header
,
/*!< in/out: 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
...
...
@@ -294,7 +297,12 @@ fseg_alloc_free_page_general(
with fsp_reserve_free_extents, then there
is no need to do the check for this individual
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
use several pages from the tablespace should call this function beforehand
...
...
storage/innobase/include/mtr0mtr.h
View file @
ab20f3b3
/*****************************************************************************
Copyright (c) 1995, 20
09, Innobase Oy
. All Rights Reserved.
Copyright (c) 1995, 20
12, Oracle and/or its affiliates
. All Rights Reserved.
This program is free software; you can redistribute it and/or modify it under
the terms of the GNU General Public License as published by the Free Software
...
...
@@ -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_X_FIX RW_X_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_X_LOCK 56
...
...
@@ -376,6 +378,9 @@ struct mtr_struct{
ulint
n_log_recs
;
/* count of how many page initial log records
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
logged; default value MTR_LOG_ALL */
ib_uint64_t
start_lsn
;
/* start lsn of the possible log entry for
...
...
storage/innobase/include/mtr0mtr.ic
View file @
ab20f3b3
/*****************************************************************************
Copyright (c) 1995, 201
0, Innobase Oy
. All Rights Reserved.
Copyright (c) 1995, 201
2, Oracle and/or its affiliates
. All Rights Reserved.
This program is free software; you can redistribute it and/or modify it under
the terms of the GNU General Public License as published by the Free Software
...
...
@@ -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.
You should have received a copy of the GNU General Public License along with
this program; if not, write to the Free Software Foundation, Inc.,
59 Temple
Place, Suite 330, Boston, MA 02111-1307
USA
this program; if not, write to the Free Software Foundation, Inc.,
51 Franklin Street, Suite 500, Boston, MA 02110-1335
USA
*****************************************************************************/
...
...
@@ -46,6 +46,7 @@ mtr_start(
mtr->modifications = FALSE;
mtr->inside_ibuf = FALSE;
mtr->n_log_recs = 0;
mtr->n_freed_pages = 0;
ut_d(mtr->state = MTR_ACTIVE);
ut_d(mtr->magic_n = MTR_MAGIC_N);
...
...
storage/innobase/include/page0page.h
View file @
ab20f3b3
/*****************************************************************************
Copyright (c) 1994, 20
09, Innobase Oy
. All Rights Reserved.
Copyright (c) 1994, 20
12, Oracle and/or its affiliates
. All Rights Reserved.
This program is free software; you can redistribute it and/or modify it under
the terms of the GNU General Public License as published by the Free Software
...
...
@@ -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.
You should have received a copy of the GNU General Public License along with
this program; if not, write to the Free Software Foundation, Inc.,
59 Temple
Place, Suite 330, Boston, MA 02111-1307
USA
this program; if not, write to the Free Software Foundation, Inc.,
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) */
#define page_get_infimum_rec(page) ((page) + page_get_infimum_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
of records in the list, returns the first record of upper half-list
.
@return
middle
record */
Returns the
nth record of the record list.
This is the inverse function of page_rec_get_n_recs_before()
.
@return
nth
record */
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
*
page_get_middle_rec
(
/*================*/
page_t
*
page
)
;
/*!< in: page */
#ifndef UNIV_HOTBACKUP
page_t
*
page
)
/*!< in: page */
__attribute__
((
nonnull
,
warn_unused_result
));
/*************************************************************//**
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
...
...
@@ -345,6 +371,7 @@ page_get_n_recs(
/***************************************************************//**
Returns the number of records before the given record in chain.
The number includes infimum and supremum records.
This is the inverse function of page_rec_get_nth().
@return number of records */
UNIV_INTERN
ulint
...
...
storage/innobase/include/page0page.ic
View file @
ab20f3b3
/*****************************************************************************
Copyright (c) 1994, 20
09, Innobase Oy
. All Rights Reserved.
Copyright (c) 1994, 20
12, Oracle and/or its affiliates
. All Rights Reserved.
This program is free software; you can redistribute it and/or modify it under
the terms of the GNU General Public License as published by the Free Software
...
...
@@ -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.
You should have received a copy of the GNU General Public License along with
this program; if not, write to the Free Software Foundation, Inc.,
59 Temple
Place, Suite 330, Boston, MA 02111-1307
USA
this program; if not, write to the Free Software Foundation, Inc.,
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)));
}
/************************************************************//**
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
/************************************************************//**
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
cmp_dtuple_rec_with_match in the way that the record must reside on an
...
...
storage/innobase/include/sync0sync.h
View file @
ab20f3b3
/*****************************************************************************
Copyright (c) 1995, 201
1, Innobase Oy
. All Rights Reserved.
Copyright (c) 1995, 201
2, Oracle and/or its affiliates
. All Rights Reserved.
Copyright (c) 2008, Google Inc.
Portions of this file contain modifications contributed and copyrighted by
...
...
@@ -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.
You should have received a copy of the GNU General Public License along with
this program; if not, write to the Free Software Foundation, Inc.,
59 Temple
Place, Suite 330, Boston, MA 02111-1307
USA
this program; if not, write to the Free Software Foundation, Inc.,
51 Franklin Street, Suite 500, Boston, MA 02110-1335
USA
*****************************************************************************/
...
...
@@ -400,8 +400,10 @@ void
sync_thread_add_level
(
/*==================*/
void
*
latch
,
/*!< in: pointer to a mutex or an rw-lock */
ulint
level
);
/*!< in: level in the latching order; if
ulint
level
,
/*!< in: level in the latching order; if
SYNC_LEVEL_VARYING, nothing is done */
ibool
relock
)
/*!< in: TRUE if re-entering an x-lock */
__attribute__
((
nonnull
));
/******************************************************************//**
Removes a latch from the thread level array if it is found there.
@return TRUE if found in the array; it is no error if the latch is
...
...
storage/innobase/include/trx0rec.ic
View file @
ab20f3b3
/*****************************************************************************
Copyright (c) 1996, 20
09, Innobase Oy
. All Rights Reserved.
Copyright (c) 1996, 20
12, Oracle and/or its affiliates
. All Rights Reserved.
This program is free software; you can redistribute it and/or modify it under
the terms of the GNU General Public License as published by the Free Software
...
...
@@ -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.
You should have received a copy of the GNU General Public License along with
this program; if not, write to the Free Software Foundation, Inc.,
59 Temple
Place, Suite 330, Boston, MA 02111-1307
USA
this program; if not, write to the Free Software Foundation, Inc.,
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)
- ut_align_offset(undo_rec, UNIV_PAGE_SIZE);
ut_ad(len < UNIV_PAGE_SIZE);
return(mem_heap_dup(heap, undo_rec, len));
}
#endif /* !UNIV_HOTBACKUP */
storage/innobase/include/trx0undo.h
View file @
ab20f3b3
/*****************************************************************************
Copyright (c) 1996, 201
1
, Oracle and/or its affiliates. All Rights Reserved.
Copyright (c) 1996, 201
2
, Oracle and/or its affiliates. All Rights Reserved.
This program is free software; you can redistribute it and/or modify it under
the terms of the GNU General Public License as published by the Free Software
...
...
@@ -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.
You should have received a copy of the GNU General Public License along with
this program; if not, write to the Free Software Foundation, Inc.,
59 Temple
Place, Suite 330, Boston, MA 02111-1307
USA
this program; if not, write to the Free Software Foundation, Inc.,
51 Franklin Street, Suite 500, Boston, MA 02110-1335
USA
*****************************************************************************/
...
...
@@ -194,16 +194,17 @@ trx_undo_get_first_rec(
mtr_t
*
mtr
);
/*!< in: mtr */
/********************************************************************//**
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
ulint
buf_block_t
*
trx_undo_add_page
(
/*==============*/
trx_t
*
trx
,
/*!< in: transaction */
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
the rollback segment mutex */
__attribute__
((
nonnull
,
warn_unused_result
));
/********************************************************************//**
Frees the last undo log page.
The caller must hold the rollback segment mutex. */
...
...
storage/innobase/mtr/mtr0mtr.c
View file @
ab20f3b3
/*****************************************************************************
Copyright (c) 1995, 20
09, Innobase Oy
. All Rights Reserved.
Copyright (c) 1995, 20
12, Oracle and/or its affiliates
. All Rights Reserved.
This program is free software; you can redistribute it and/or modify it under
the terms of the GNU General Public License as published by the Free Software
...
...
storage/innobase/page/page0cur.c
View file @
ab20f3b3
/*****************************************************************************
Copyright (c) 1994, 20
09, Innobase Oy
. All Rights Reserved.
Copyright (c) 1994, 20
12, Oracle and/or its affiliates
. All Rights Reserved.
This program is free software; you can redistribute it and/or modify it under
the terms of the GNU General Public License as published by the Free Software
...
...
@@ -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.
You should have received a copy of the GNU General Public License along with
this program; if not, write to the Free Software Foundation, Inc.,
59 Temple
Place, Suite 330, Boston, MA 02111-1307
USA
this program; if not, write to the Free Software Foundation, Inc.,
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,
store the number of preceding records on the page. */
pos
=
page_rec_get_n_recs_before
(
rec
);
ut_ad
(
pos
>
0
);
if
(
page_zip_reorganize
(
block
,
index
,
mtr
))
{
/* The page was reorganized: Find rec by seeking to pos,
and update *current_rec. */
rec
=
page
+
PAGE_NEW_INFIMUM
;
while
(
--
pos
)
{
rec
=
page
+
rec_get_next_offs
(
rec
,
TRUE
)
;
if
(
pos
>
1
)
{
rec
=
page_rec_get_nth
(
page
,
pos
-
1
);
}
else
{
rec
=
page
+
PAGE_NEW_INFIMUM
;
}
*
current_rec
=
rec
;
...
...
@@ -1283,6 +1284,12 @@ page_cur_insert_rec_zip(
insert_rec
=
page_cur_insert_rec_zip_reorg
(
current_rec
,
block
,
index
,
insert_rec
,
page
,
page_zip
,
mtr
);
#ifdef UNIV_DEBUG
if
(
insert_rec
)
{
rec_offs_make_valid
(
insert_rec
,
index
,
offsets
);
}
#endif
/* UNIV_DEBUG */
}
return
(
insert_rec
);
...
...
storage/innobase/page/page0page.c
View file @
ab20f3b3
...
...
@@ -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.
You should have received a copy of the GNU General Public License along with
this program; if not, write to the Free Software Foundation, Inc.,
59 Temple
Place, Suite 330, Boston, MA 02111-1307
USA
this program; if not, write to the Free Software Foundation, Inc.,
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
of records in the list, returns the first record of the upper half-list
.
@return
middle
record */
Returns the
nth record of the record list.
This is the inverse function of page_rec_get_n_recs_before()
.
@return
nth
record */
UNIV_INTERN
rec_t
*
page_get_middle_rec
(
/*================*/
page_t
*
page
)
/*!< in: page */
const
rec_t
*
page_rec_get_nth_const
(
/*===================*/
const
page_t
*
page
,
/*!< in: page */
ulint
nth
)
/*!< in: nth record */
{
page_dir_slot_t
*
slot
;
ulint
middle
;
const
page_dir_slot_t
*
slot
;
ulint
i
;
ulint
n_owned
;
ulint
count
;
rec_t
*
rec
;
/* This many records we must leave behind */
middle
=
(
page_get_n_recs
(
page
)
+
PAGE_HEAP_NO_USER_LOW
)
/
2
;
const
rec_t
*
rec
;
count
=
0
;
ut_ad
(
nth
<
UNIV_PAGE_SIZE
/
(
REC_N_NEW_EXTRA_BYTES
+
1
))
;
for
(
i
=
0
;;
i
++
)
{
slot
=
page_dir_get_nth_slot
(
page
,
i
);
n_owned
=
page_dir_slot_get_n_owned
(
slot
);
if
(
count
+
n_owned
>
middle
)
{
if
(
n_owned
>
nth
)
{
break
;
}
else
{
count
+
=
n_owned
;
nth
-
=
n_owned
;
}
}
ut_ad
(
i
>
0
);
slot
=
page_dir_get_nth_slot
(
page
,
i
-
1
);
rec
=
(
rec_t
*
)
page_dir_slot_get_rec
(
slot
);
rec
=
page_rec_get_next
(
rec
);
/* There are now count records behind rec */
rec
=
page_dir_slot_get_rec
(
slot
);
for
(
i
=
0
;
i
<
middle
-
count
;
i
++
)
{
rec
=
page_rec_get_next
(
rec
);
if
(
page_is_comp
(
page
))
{
do
{
rec
=
page_rec_get_next_low
(
rec
,
TRUE
);
ut_ad
(
rec
);
}
while
(
nth
--
);
}
else
{
do
{
rec
=
page_rec_get_next_low
(
rec
,
FALSE
);
ut_ad
(
rec
);
}
while
(
nth
--
);
}
return
(
rec
);
}
#endif
/* !UNIV_HOTBACKUP */
/***************************************************************//**
Returns the number of records before the given record in chain.
...
...
@@ -1564,6 +1563,7 @@ page_rec_get_n_recs_before(
n
--
;
ut_ad
(
n
>=
0
);
ut_ad
(
n
<
UNIV_PAGE_SIZE
/
(
REC_N_NEW_EXTRA_BYTES
+
1
));
return
((
ulint
)
n
);
}
...
...
storage/innobase/row/row0ins.c
View file @
ab20f3b3
...
...
@@ -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.
You should have received a copy of the GNU General Public License along with
this program; if not, write to the Free Software Foundation, Inc.,
59 Temple
Place, Suite 330, Boston, MA 02111-1307
USA
this program; if not, write to the Free Software Foundation, Inc.,
51 Franklin Street, Suite 500, Boston, MA 02110-1335
USA
*****************************************************************************/
...
...
@@ -23,7 +23,6 @@ Insert into a table
Created 4/20/1996 Heikki Tuuri
*******************************************************/
#include "my_global.h"
/* HAVE_* */
#include "m_string.h"
/* for my_sys.h */
#include "my_sys.h"
/* DEBUG_SYNC_C */
#include "row0ins.h"
...
...
@@ -351,9 +350,9 @@ row_ins_clust_index_entry_by_modify(
return
(
DB_LOCK_TABLE_FULL
);
}
err
=
btr_cur_pessimistic_update
(
0
,
cursor
,
heap
,
big_rec
,
update
,
0
,
thr
,
mtr
);
err
=
btr_cur_pessimistic_update
(
BTR_KEEP_POS_FLAG
,
cursor
,
heap
,
big_rec
,
update
,
0
,
thr
,
mtr
);
}
return
(
err
);
...
...
@@ -1982,6 +1981,7 @@ row_ins_index_entry_low(
ulint
modify
=
0
;
/* remove warning */
rec_t
*
insert_rec
;
rec_t
*
rec
;
ulint
*
offsets
;
ulint
err
;
ulint
n_unique
;
big_rec_t
*
big_rec
=
NULL
;
...
...
@@ -2089,6 +2089,64 @@ row_ins_index_entry_low(
err
=
row_ins_clust_index_entry_by_modify
(
mode
,
&
cursor
,
&
heap
,
&
big_rec
,
entry
,
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
{
ut_ad
(
!
n_ext
);
err
=
row_ins_sec_index_entry_by_modify
(
...
...
@@ -2117,9 +2175,6 @@ function_exit:
mtr_commit
(
&
mtr
);
if
(
UNIV_LIKELY_NULL
(
big_rec
))
{
rec_t
*
rec
;
ulint
*
offsets
;
DBUG_EXECUTE_IF
(
"row_ins_extern_checkpoint"
,
log_make_checkpoint_at
(
IB_ULONGLONG_MAX
,
TRUE
););
...
...
@@ -2134,12 +2189,13 @@ function_exit:
offsets
=
rec_get_offsets
(
rec
,
index
,
NULL
,
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
(
index
,
btr_cur_get_block
(
&
cursor
),
rec
,
offsets
,
&
mtr
,
FALSE
,
big_rec
);
DEBUG_SYNC_C
(
"after_row_ins_
upd_
extern"
);
rec
,
offsets
,
big_rec
,
&
mtr
,
BTR_STORE_INSERT
);
DEBUG_SYNC_C
(
"after_row_ins_extern"
);
stored_big_rec:
if
(
modify
)
{
dtuple_big_rec_free
(
big_rec
);
}
else
{
...
...
storage/innobase/row/row0row.c
View file @
ab20f3b3
/*****************************************************************************
Copyright (c) 1996, 201
1
, Oracle and/or its affiliates. All Rights Reserved.
Copyright (c) 1996, 201
2
, Oracle and/or its affiliates. All Rights Reserved.
This program is free software; you can redistribute it and/or modify it under
the terms of the GNU General Public License as published by the Free Software
...
...
@@ -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.
You should have received a copy of the GNU General Public License along with
this program; if not, write to the Free Software Foundation, Inc.,
59 Temple
Place, Suite 330, Boston, MA 02111-1307
USA
this program; if not, write to the Free Software Foundation, Inc.,
51 Franklin Street, Suite 500, Boston, MA 02110-1335
USA
*****************************************************************************/
...
...
@@ -241,13 +241,22 @@ row_build(
ut_ad
(
rec_offs_validate
(
rec
,
index
,
offsets
));
}
#if 0 && defined UNIV_BLOB_NULL_DEBUG
/* This one can fail in trx_rollback_active() if
the server crashed during an insert before the
btr_store_big_rec_extern_fields() did mtr_commit()
all BLOB pointers to the clustered index record. */
ut_a(!rec_offs_any_null_extern(rec, offsets));
#endif /* 0 && UNIV_BLOB_NULL_DEBUG */
#ifdef UNIV_BLOB_NULL_DEBUG
if
(
rec_offs_any_null_extern
(
rec
,
offsets
))
{
/* This condition can occur during crash recovery
before trx_rollback_active() has completed execution.
This condition is possible if the server crashed
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
)
{
/* Take a copy of rec to heap */
...
...
storage/innobase/row/row0upd.c
View file @
ab20f3b3
...
...
@@ -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.
You should have received a copy of the GNU General Public License along with
this program; if not, write to the Free Software Foundation, Inc.,
59 Temple
Place, Suite 330, Boston, MA 02111-1307
USA
this program; if not, write to the Free Software Foundation, Inc.,
51 Franklin Street, Suite 500, Boston, MA 02110-1335
USA
*****************************************************************************/
...
...
@@ -23,7 +23,6 @@ Update of a row
Created 12/27/1996 Heikki Tuuri
*******************************************************/
#include "my_global.h"
/* HAVE_* */
#include "m_string.h"
/* for my_sys.h */
#include "my_sys.h"
/* DEBUG_SYNC_C */
#include "row0upd.h"
...
...
@@ -2003,33 +2002,62 @@ row_upd_clust_rec(
ut_ad
(
!
rec_get_deleted_flag
(
btr_pcur_get_rec
(
pcur
),
dict_table_is_comp
(
index
->
table
)));
err
=
btr_cur_pessimistic_update
(
BTR_NO_LOCKING_FLAG
,
btr_cur
,
&
heap
,
&
big_rec
,
node
->
update
,
node
->
cmpl_info
,
thr
,
mtr
);
mtr_commit
(
mtr
);
if
(
err
==
DB_SUCCESS
&&
big_rec
)
{
ulint
offsets_
[
REC_OFFS_NORMAL_SIZE
];
rec_t
*
rec
;
err
=
btr_cur_pessimistic_update
(
BTR_NO_LOCKING_FLAG
|
BTR_KEEP_POS_FLAG
,
btr_cur
,
&
heap
,
&
big_rec
,
node
->
update
,
node
->
cmpl_info
,
thr
,
mtr
);
if
(
big_rec
)
{
ulint
offsets_
[
REC_OFFS_NORMAL_SIZE
];
rec_t
*
rec
;
rec_offs_init
(
offsets_
);
DBUG_EXECUTE_IF
(
"row_upd_extern_checkpoint"
,
log_make_checkpoint_at
(
IB_ULONGLONG_MAX
,
TRUE
););
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. */
mtr_start
(
mtr
);
ut_a
(
btr_pcur_restore_position
(
BTR_MODIFY_TREE
,
pcur
,
mtr
));
rec
=
btr_cur_get_rec
(
btr_cur
);
DEBUG_SYNC_C
(
"before_row_upd_extern"
);
err
=
btr_store_big_rec_extern_fields
(
index
,
btr_cur_get_block
(
btr_cur
),
rec
,
rec_get_offsets
(
rec
,
index
,
offsets_
,
ULINT_UNDEFINED
,
&
heap
),
mtr
,
TRUE
,
big_rec
);
big_rec
,
mtr
,
BTR_STORE_UPDATE
);
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
))
{
mem_heap_free
(
heap
);
}
...
...
storage/innobase/sync/sync0rw.c
View file @
ab20f3b3
/*****************************************************************************
Copyright (c) 1995, 201
1
, Oracle and/or its affiliates. All Rights Reserved.
Copyright (c) 1995, 201
2
, Oracle and/or its affiliates. All Rights Reserved.
Copyright (c) 2008, Google Inc.
Portions of this file contain modifications contributed and copyrighted by
...
...
@@ -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.
You should have received a copy of the GNU General Public License along with
this program; if not, write to the Free Software Foundation, Inc.,
59 Temple
Place, Suite 330, Boston, MA 02111-1307
USA
this program; if not, write to the Free Software Foundation, Inc.,
51 Franklin Street, Suite 500, Boston, MA 02110-1335
USA
*****************************************************************************/
...
...
@@ -785,7 +785,9 @@ rw_lock_add_debug_info(
rw_lock_debug_mutex_exit
();
if
((
pass
==
0
)
&&
(
lock_type
!=
RW_LOCK_WAIT_EX
))
{
sync_thread_add_level
(
lock
,
lock
->
level
);
sync_thread_add_level
(
lock
,
lock
->
level
,
lock_type
==
RW_LOCK_EX
&&
lock
->
lock_word
<
0
);
}
}
...
...
storage/innobase/sync/sync0sync.c
View file @
ab20f3b3
/*****************************************************************************
Copyright (c) 1995, 201
1, Innobase Oy
. All Rights Reserved.
Copyright (c) 1995, 201
2, Oracle and/or its affiliates
. All Rights Reserved.
Copyright (c) 2008, Google Inc.
Portions of this file contain modifications contributed and copyrighted by
...
...
@@ -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.
You should have received a copy of the GNU General Public License along with
this program; if not, write to the Free Software Foundation, Inc.,
59 Temple
Place, Suite 330, Boston, MA 02111-1307
USA
this program; if not, write to the Free Software Foundation, Inc.,
51 Franklin Street, Suite 500, Boston, MA 02110-1335
USA
*****************************************************************************/
...
...
@@ -690,7 +690,7 @@ mutex_set_debug_info(
ut_ad
(
mutex
);
ut_ad
(
file_name
);
sync_thread_add_level
(
mutex
,
mutex
->
level
);
sync_thread_add_level
(
mutex
,
mutex
->
level
,
FALSE
);
mutex
->
file_name
=
file_name
;
mutex
->
line
=
line
;
...
...
@@ -1133,8 +1133,9 @@ void
sync_thread_add_level
(
/*==================*/
void
*
latch
,
/*!< in: pointer to a mutex or an rw-lock */
ulint
level
)
/*!< in: level in the latching order; if
ulint
level
,
/*!< in: level in the latching order; if
SYNC_LEVEL_VARYING, nothing is done */
ibool
relock
)
/*!< in: TRUE if re-entering an x-lock */
{
ulint
i
;
sync_level_t
*
slot
;
...
...
@@ -1185,6 +1186,10 @@ sync_thread_add_level(
array
=
thread_slot
->
levels
;
if
(
relock
)
{
goto
levels_ok
;
}
/* NOTE that there is a problem with _NODE and _LEAF levels: if the
B-tree height changes, then a leaf can change to an internal node
or the other way around. We do not know at present if this can cause
...
...
@@ -1360,6 +1365,7 @@ sync_thread_add_level(
ut_error
;
}
levels_ok:
if
(
array
->
next_free
==
ULINT_UNDEFINED
)
{
ut_a
(
array
->
n_elems
<
array
->
max_elems
);
...
...
storage/innobase/trx/trx0rec.c
View file @
ab20f3b3
...
...
@@ -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.
You should have received a copy of the GNU General Public License along with
this program; if not, write to the Free Software Foundation, Inc.,
59 Temple
Place, Suite 330, Boston, MA 02111-1307
USA
this program; if not, write to the Free Software Foundation, Inc.,
51 Franklin Street, Suite 500, Boston, MA 02110-1335
USA
*****************************************************************************/
...
...
@@ -1198,6 +1198,7 @@ trx_undo_report_row_operation(
trx_t
*
trx
;
trx_undo_t
*
undo
;
ulint
page_no
;
buf_block_t
*
undo_block
;
trx_rseg_t
*
rseg
;
mtr_t
mtr
;
ulint
err
=
DB_SUCCESS
;
...
...
@@ -1240,10 +1241,13 @@ trx_undo_report_row_operation(
if
(
UNIV_UNLIKELY
(
!
undo
))
{
/* Did not succeed */
ut_ad
(
err
!=
DB_SUCCESS
);
mutex_exit
(
&
(
trx
->
undo_mutex
));
return
(
err
);
}
ut_ad
(
err
==
DB_SUCCESS
);
}
else
{
ut_ad
(
op_type
==
TRX_UNDO_MODIFY_OP
);
...
...
@@ -1257,30 +1261,30 @@ trx_undo_report_row_operation(
if
(
UNIV_UNLIKELY
(
!
undo
))
{
/* Did not succeed */
ut_ad
(
err
!=
DB_SUCCESS
);
mutex_exit
(
&
(
trx
->
undo_mutex
));
return
(
err
);
}
ut_ad
(
err
==
DB_SUCCESS
);
offsets
=
rec_get_offsets
(
rec
,
index
,
offsets
,
ULINT_UNDEFINED
,
&
heap
);
}
page_no
=
undo
->
last_page_no
;
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
{
buf_block_t
*
undo_block
;
page_t
*
undo_page
;
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
);
ut_ad
(
page_no
==
buf_block_get_page_no
(
undo_block
));
if
(
op_type
==
TRX_UNDO_INSERT_OP
)
{
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
counterpart of the tree latch, which is the rseg mutex. */
mutex_enter
(
&
(
rseg
->
mutex
));
page_no
=
trx_undo_add_page
(
trx
,
undo
,
&
mtr
);
mutex_exit
(
&
(
rseg
->
mutex
));
}
while
(
UNIV_LIKELY
(
page_no
!=
FIL_NULL
));
mutex_enter
(
&
rseg
->
mutex
);
undo_block
=
trx_undo_add_page
(
trx
,
undo
,
&
mtr
);
mutex_exit
(
&
rseg
->
mutex
);
page_no
=
undo
->
last_page_no
;
}
while
(
undo_block
!=
NULL
);
/* Did not succeed: out of space */
err
=
DB_OUT_OF_FILE_SPACE
;
...
...
storage/innobase/trx/trx0sys.c
View file @
ab20f3b3
/*****************************************************************************
Copyright (c) 1996, 201
1, Innobase Oy
. All Rights Reserved.
Copyright (c) 1996, 201
2, Oracle and/or its affiliates
. All Rights Reserved.
This program is free software; you can redistribute it and/or modify it under
the terms of the GNU General Public License as published by the Free Software
...
...
@@ -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.
You should have received a copy of the GNU General Public License along with
this program; if not, write to the Free Software Foundation, Inc.,
59 Temple
Place, Suite 330, Boston, MA 02111-1307
USA
this program; if not, write to the Free Software Foundation, Inc.,
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
*
block2
;
#ifdef UNIV_SYNC_DEBUG
buf_block_t
*
new_block
;
#endif
/* UNIV_SYNC_DEBUG */
byte
*
doublewrite
;
byte
*
fseg_header
;
ulint
page_no
;
...
...
@@ -336,10 +334,9 @@ start_again:
for
(
i
=
0
;
i
<
2
*
TRX_SYS_DOUBLEWRITE_BLOCK_SIZE
+
FSP_EXTENT_SIZE
/
2
;
i
++
)
{
page_no
=
fseg_alloc_free_page
(
fseg_header
,
prev_page_no
+
1
,
FSP_UP
,
&
mtr
);
if
(
page_no
==
FIL_NULL
)
{
new_block
=
fseg_alloc_free_page
(
fseg_header
,
prev_page_no
+
1
,
FSP_UP
,
&
mtr
);
if
(
new_block
==
NULL
)
{
fprintf
(
stderr
,
"InnoDB: Cannot create doublewrite"
" buffer: you must
\n
"
...
...
@@ -360,13 +357,8 @@ start_again:
the page position in the tablespace, then the page
has not been written to in doublewrite. */
#ifdef UNIV_SYNC_DEBUG
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
);
ut_ad
(
rw_lock_get_x_lock_count
(
&
new_block
->
lock
)
==
1
);
page_no
=
buf_block_get_page_no
(
new_block
);
if
(
i
==
FSP_EXTENT_SIZE
/
2
)
{
ut_a
(
page_no
==
FSP_EXTENT_SIZE
);
...
...
storage/innobase/trx/trx0undo.c
View file @
ab20f3b3
/*****************************************************************************
Copyright (c) 1996, 20
09, Innobase Oy
. All Rights Reserved.
Copyright (c) 1996, 20
12, Oracle and/or its affiliates
. All Rights Reserved.
This program is free software; you can redistribute it and/or modify it under
the terms of the GNU General Public License as published by the Free Software
...
...
@@ -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.
You should have received a copy of the GNU General Public License along with
this program; if not, write to the Free Software Foundation, Inc.,
59 Temple
Place, Suite 330, Boston, MA 02111-1307
USA
this program; if not, write to the Free Software Foundation, Inc.,
51 Franklin Street, Suite 500, Boston, MA 02110-1335
USA
*****************************************************************************/
...
...
@@ -876,9 +876,9 @@ trx_undo_discard_latest_update_undo(
#ifndef UNIV_HOTBACKUP
/********************************************************************//**
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
ulint
buf_block_t
*
trx_undo_add_page
(
/*==============*/
trx_t
*
trx
,
/*!< in: transaction */
...
...
@@ -888,11 +888,10 @@ trx_undo_add_page(
the rollback segment mutex */
{
page_t
*
header_page
;
buf_block_t
*
new_block
;
page_t
*
new_page
;
trx_rseg_t
*
rseg
;
ulint
page_no
;
ulint
n_reserved
;
ibool
success
;
ut_ad
(
mutex_own
(
&
(
trx
->
undo_mutex
)));
ut_ad
(
!
mutex_own
(
&
kernel_mutex
));
...
...
@@ -902,37 +901,37 @@ trx_undo_add_page(
if
(
rseg
->
curr_size
==
rseg
->
max_size
)
{
return
(
FIL_
NULL
);
return
(
NULL
);
}
header_page
=
trx_undo_page_get
(
undo
->
space
,
undo
->
zip_size
,
undo
->
hdr_page_no
,
mtr
);
success
=
fsp_reserve_free_extents
(
&
n_reserved
,
undo
->
space
,
1
,
FSP_UNDO
,
mtr
);
if
(
!
success
)
{
if
(
!
fsp_reserve_free_extents
(
&
n_reserved
,
undo
->
space
,
1
,
FSP_UNDO
,
mtr
))
{
return
(
FIL_
NULL
);
return
(
NULL
);
}
page_no
=
fseg_alloc_free_page_general
(
header_page
+
TRX_UNDO_SEG_HDR
+
TRX_UNDO_FSEG_HEADER
,
undo
->
top_page_no
+
1
,
FSP_UP
,
TRUE
,
mtr
);
new_block
=
fseg_alloc_free_page_general
(
TRX_UNDO_SEG_HDR
+
TRX_UNDO_FSEG_HEADER
+
header_page
,
undo
->
top_page_no
+
1
,
FSP_UP
,
TRUE
,
mtr
,
mtr
);
fil_space_release_free_extents
(
undo
->
space
,
n_reserved
);
if
(
page_no
==
FIL_
NULL
)
{
if
(
new_block
==
NULL
)
{
/* 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
,
page_no
,
mtr
);
new_page
=
buf_block_get_frame
(
new_block
);
trx_undo_page_init
(
new_page
,
undo
->
type
,
mtr
);
...
...
@@ -941,7 +940,7 @@ trx_undo_add_page(
undo
->
size
++
;
rseg
->
curr_size
++
;
return
(
page_no
);
return
(
new_block
);
}
/********************************************************************//**
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment