[Commits] bcc92bd: - WL#6326 : InnoDB: fix index->lock contention

Jan Lindström jan.lindstrom at mariadb.com
Thu Mar 26 09:59:07 EET 2015


revision-id: bcc92bde1a7f9d5ff9b38d714d66d5a0d466360b
parent(s): cabbeac1c3e70568cd4dd549af4c7f7f651a13f4
committer: Jan Lindström
branch nick: 10.1-innodb-merge
timestamp: 2015-03-26 09:58:52 +0200
message:

- WL#6326 : InnoDB: fix index->lock contention

The acquisition of node pointer page latches is protected by index->lock latch.

Before WL#6326, index->lock protected all node pointer pages either in S or X
mode, and no individual block->lock were acquired on node pointer pages.

After WL#6326, node pointer pages are protected by individual block->lock
S-latch or X-latch. The acquisition of node pointer page latches is covered by
index->lock, for preventing deadlocks.

This WL# depends on WL#6363

(rb#1099 : Approved by Kevin and Jimmy)

- WL#6363 : implement SX-lock for rw_lock

InnoDB internally uses rw-lock implementation to keep consistency of internal
resources. Basically the rw-lock has 2 types S-lock (shared) and X-lock (exluded).
The fix adds the new type SX-lock (shared excluded) for room to optimize
concurrency and improve scalability more.

At least, S-lock and X-lock behave same, and compatible for current code. So,
nothing changed by only this fix as it is. (no functional/performance changes
for users)

The new state SX-lock will be used by the future work. (e.g. WL#6326: InnoDB:
fix index->lock contention)

new state of rw_lock: SX-lock
      | S|SX| X|
    --+--+--+--+
     S| o| o| x|
    --+--+--+--+
    SX| o| x| x|
    --+--+--+--+
     X| x| x| x|
    --+--+--+--+

(rb#1098 : Approved by Inaam and Kevin)

Conflicts:
	storage/innobase/btr/btr0btr.cc
	storage/innobase/btr/btr0cur.cc
	storage/innobase/buf/buf0flu.cc
	storage/innobase/dict/dict0stats.cc
	storage/innobase/fsp/fsp0fsp.cc
	storage/innobase/handler/ha_innodb.cc
	storage/innobase/ibuf/ibuf0ibuf.cc
	storage/innobase/include/btr0btr.h
	storage/innobase/include/btr0btr.ic
	storage/innobase/include/dict0dict.h
	storage/innobase/include/mtr0log.ic
	storage/innobase/include/mtr0mtr.h
	storage/innobase/include/mtr0mtr.ic
	storage/innobase/include/sync0rw.h
	storage/innobase/include/sync0rw.ic
	storage/innobase/mtr/mtr0mtr.cc
	storage/innobase/sync/sync0arr.cc
	storage/innobase/sync/sync0rw.cc

---
 mysql-test/suite/innodb/r/innodb_wl6326.result     |  341 ++++++
 mysql-test/suite/innodb/r/innodb_wl6326_big.result |  445 ++++++++
 mysql-test/suite/innodb/t/innodb_wl6326.opt        |    1 +
 mysql-test/suite/innodb/t/innodb_wl6326.test       |  500 +++++++++
 mysql-test/suite/innodb/t/innodb_wl6326_big.test   |  696 ++++++++++++
 storage/innobase/btr/btr0btr.cc                    |  278 +++--
 storage/innobase/btr/btr0cur.cc                    | 1140 ++++++++++++++++++--
 storage/innobase/btr/btr0pcur.cc                   |   17 +-
 storage/innobase/buf/buf0buf.cc                    |   29 +-
 storage/innobase/buf/buf0flu.cc                    |   12 +-
 storage/innobase/data/data0data.cc                 |    2 +-
 storage/innobase/dict/dict0dict.cc                 |  102 +-
 storage/innobase/dict/dict0stats.cc                |   12 +-
 storage/innobase/fsp/fsp0fsp.cc                    |  149 ++-
 storage/innobase/fut/fut0lst.cc                    |   98 +-
 storage/innobase/handler/ha_innodb.cc              |    2 +-
 storage/innobase/ibuf/ibuf0ibuf.cc                 |   34 +-
 storage/innobase/include/btr0btr.h                 |   33 +-
 storage/innobase/include/btr0btr.ic                |    6 +-
 storage/innobase/include/btr0pcur.ic               |    2 +-
 storage/innobase/include/btr0types.h               |    4 +
 storage/innobase/include/buf0buf.ic                |    9 +-
 storage/innobase/include/buf0flu.ic                |    3 +-
 storage/innobase/include/dict0dict.h               |   20 +-
 storage/innobase/include/fut0fut.ic                |    4 +-
 storage/innobase/include/fut0lst.ic                |    8 +-
 storage/innobase/include/mtr0mtr.h                 |   18 +-
 storage/innobase/include/page0page.h               |   45 +
 storage/innobase/include/page0page.ic              |   63 ++
 storage/innobase/include/row0log.ic                |    6 +-
 storage/innobase/include/sync0rw.h                 |   26 +-
 storage/innobase/mtr/mtr0mtr.cc                    |   67 +-
 storage/innobase/rem/rem0cmp.cc                    |    6 +-
 storage/innobase/row/row0import.cc                 |    3 +-
 storage/innobase/row/row0ins.cc                    |    6 +-
 storage/innobase/row/row0log.cc                    |   30 +-
 storage/innobase/row/row0merge.cc                  |    3 +-
 storage/innobase/row/row0purge.cc                  |   18 +-
 storage/innobase/row/row0uins.cc                   |   15 +-
 storage/innobase/row/row0umod.cc                   |   23 +-
 storage/innobase/sync/sync0rw.cc                   |   34 +-
 41 files changed, 3962 insertions(+), 348 deletions(-)

diff --git a/mysql-test/suite/innodb/r/innodb_wl6326.result b/mysql-test/suite/innodb/r/innodb_wl6326.result
new file mode 100644
index 0000000..d4710bf
--- /dev/null
+++ b/mysql-test/suite/innodb/r/innodb_wl6326.result
@@ -0,0 +1,341 @@
+DROP TABLE IF EXISTS t1;
+SET GLOBAL innodb_adaptive_hash_index = false;
+SET GLOBAL innodb_stats_persistent = false;
+CREATE TABLE t1 (
+a00 CHAR(255) NOT NULL DEFAULT 'a',
+a01 CHAR(255) NOT NULL DEFAULT 'a',
+a02 CHAR(255) NOT NULL DEFAULT 'a',
+a03 CHAR(255) NOT NULL DEFAULT 'a',
+a04 CHAR(255) NOT NULL DEFAULT 'a',
+a05 CHAR(255) NOT NULL DEFAULT 'a',
+a06 CHAR(255) NOT NULL DEFAULT 'a',
+b INT NOT NULL DEFAULT 0
+) ENGINE = InnoDB;
+ALTER TABLE t1 ADD CONSTRAINT pkey PRIMARY KEY(
+a00,
+a01,
+a02,
+a03,
+a04,
+a05,
+a06
+);
+ANALYZE TABLE t1;
+Table	Op	Msg_type	Msg_text
+test.t1	analyze	status	OK
+SELECT CLUST_INDEX_SIZE FROM information_schema.INNODB_SYS_TABLESTATS WHERE NAME = 'test/t1';
+CLUST_INDEX_SIZE
+1
+SET GLOBAL innodb_limit_optimistic_insert_debug = 7;
+INSERT INTO t1 (a00) VALUES ('aa');
+INSERT INTO t1 (a00) VALUES ('ab');
+INSERT INTO t1 (a00) VALUES ('ac');
+INSERT INTO t1 (a00) VALUES ('ad');
+INSERT INTO t1 (a00) VALUES ('ae');
+INSERT INTO t1 (a00) VALUES ('af');
+INSERT INTO t1 (a00) VALUES ('ag');
+INSERT INTO t1 (a00) VALUES ('ah');
+ANALYZE TABLE t1;
+Table	Op	Msg_type	Msg_text
+test.t1	analyze	status	OK
+SELECT CLUST_INDEX_SIZE FROM information_schema.INNODB_SYS_TABLESTATS WHERE NAME = 'test/t1';
+CLUST_INDEX_SIZE
+3
+INSERT INTO t1 (a00) VALUES ('ai');
+INSERT INTO t1 (a00) VALUES ('aj');
+INSERT INTO t1 (a00) VALUES ('ak');
+ANALYZE TABLE t1;
+Table	Op	Msg_type	Msg_text
+test.t1	analyze	status	OK
+SELECT CLUST_INDEX_SIZE FROM information_schema.INNODB_SYS_TABLESTATS WHERE NAME = 'test/t1';
+CLUST_INDEX_SIZE
+4
+INSERT INTO t1 (a00) VALUES ('al');
+INSERT INTO t1 (a00) VALUES ('am');
+INSERT INTO t1 (a00) VALUES ('an');
+INSERT INTO t1 (a00) VALUES ('ao');
+INSERT INTO t1 (a00) VALUES ('ap');
+INSERT INTO t1 (a00) VALUES ('aq');
+INSERT INTO t1 (a00) VALUES ('ar');
+ANALYZE TABLE t1;
+Table	Op	Msg_type	Msg_text
+test.t1	analyze	status	OK
+SELECT CLUST_INDEX_SIZE FROM information_schema.INNODB_SYS_TABLESTATS WHERE NAME = 'test/t1';
+CLUST_INDEX_SIZE
+5
+INSERT INTO t1 (a00) VALUES ('as');
+INSERT INTO t1 (a00) VALUES ('at');
+INSERT INTO t1 (a00) VALUES ('au');
+INSERT INTO t1 (a00) VALUES ('av');
+INSERT INTO t1 (a00) VALUES ('aw');
+INSERT INTO t1 (a00) VALUES ('ax');
+INSERT INTO t1 (a00) VALUES ('ay');
+ANALYZE TABLE t1;
+Table	Op	Msg_type	Msg_text
+test.t1	analyze	status	OK
+SELECT CLUST_INDEX_SIZE FROM information_schema.INNODB_SYS_TABLESTATS WHERE NAME = 'test/t1';
+CLUST_INDEX_SIZE
+6
+INSERT INTO t1 (a00) VALUES ('az');
+INSERT INTO t1 (a00) VALUES ('ba');
+INSERT INTO t1 (a00) VALUES ('bb');
+INSERT INTO t1 (a00) VALUES ('bc');
+INSERT INTO t1 (a00) VALUES ('bd');
+INSERT INTO t1 (a00) VALUES ('be');
+INSERT INTO t1 (a00) VALUES ('bf');
+ANALYZE TABLE t1;
+Table	Op	Msg_type	Msg_text
+test.t1	analyze	status	OK
+SELECT CLUST_INDEX_SIZE FROM information_schema.INNODB_SYS_TABLESTATS WHERE NAME = 'test/t1';
+CLUST_INDEX_SIZE
+7
+INSERT INTO t1 (a00) VALUES ('bg');
+INSERT INTO t1 (a00) VALUES ('bh');
+INSERT INTO t1 (a00) VALUES ('bi');
+INSERT INTO t1 (a00) VALUES ('bj');
+INSERT INTO t1 (a00) VALUES ('bk');
+INSERT INTO t1 (a00) VALUES ('bl');
+INSERT INTO t1 (a00) VALUES ('bm');
+ANALYZE TABLE t1;
+Table	Op	Msg_type	Msg_text
+test.t1	analyze	status	OK
+SELECT CLUST_INDEX_SIZE FROM information_schema.INNODB_SYS_TABLESTATS WHERE NAME = 'test/t1';
+CLUST_INDEX_SIZE
+8
+INSERT INTO t1 (a00) VALUES ('bn');
+INSERT INTO t1 (a00) VALUES ('bo');
+INSERT INTO t1 (a00) VALUES ('bp');
+INSERT INTO t1 (a00) VALUES ('bq');
+INSERT INTO t1 (a00) VALUES ('br');
+INSERT INTO t1 (a00) VALUES ('bs');
+INSERT INTO t1 (a00) VALUES ('bt');
+ANALYZE TABLE t1;
+Table	Op	Msg_type	Msg_text
+test.t1	analyze	status	OK
+SELECT CLUST_INDEX_SIZE FROM information_schema.INNODB_SYS_TABLESTATS WHERE NAME = 'test/t1';
+CLUST_INDEX_SIZE
+11
+INSERT INTO t1 (a00) VALUES ('bu');
+INSERT INTO t1 (a00) VALUES ('bv');
+INSERT INTO t1 (a00) VALUES ('bw');
+INSERT INTO t1 (a00) VALUES ('bx');
+INSERT INTO t1 (a00) VALUES ('by');
+INSERT INTO t1 (a00) VALUES ('bz');
+INSERT INTO t1 (a00) VALUES ('ca');
+INSERT INTO t1 (a00) VALUES ('cb');
+INSERT INTO t1 (a00) VALUES ('cc');
+INSERT INTO t1 (a00) VALUES ('cd');
+INSERT INTO t1 (a00) VALUES ('ce');
+INSERT INTO t1 (a00) VALUES ('cf');
+INSERT INTO t1 (a00) VALUES ('cg');
+INSERT INTO t1 (a00) VALUES ('ch');
+INSERT INTO t1 (a00) VALUES ('ci');
+INSERT INTO t1 (a00) VALUES ('cj');
+INSERT INTO t1 (a00) VALUES ('ck');
+INSERT INTO t1 (a00) VALUES ('cl');
+INSERT INTO t1 (a00) VALUES ('cm');
+INSERT INTO t1 (a00) VALUES ('cn');
+INSERT INTO t1 (a00) VALUES ('co');
+ANALYZE TABLE t1;
+Table	Op	Msg_type	Msg_text
+test.t1	analyze	status	OK
+SELECT CLUST_INDEX_SIZE FROM information_schema.INNODB_SYS_TABLESTATS WHERE NAME = 'test/t1';
+CLUST_INDEX_SIZE
+15
+INSERT INTO t1 (a00) VALUES ('cp');
+INSERT INTO t1 (a00) VALUES ('cq');
+INSERT INTO t1 (a00) VALUES ('cr');
+INSERT INTO t1 (a00) VALUES ('cs');
+INSERT INTO t1 (a00) VALUES ('ct');
+INSERT INTO t1 (a00) VALUES ('cu');
+INSERT INTO t1 (a00) VALUES ('cv');
+INSERT INTO t1 (a00) VALUES ('cw');
+INSERT INTO t1 (a00) VALUES ('cx');
+INSERT INTO t1 (a00) VALUES ('cy');
+INSERT INTO t1 (a00) VALUES ('cz');
+INSERT INTO t1 (a00) VALUES ('da');
+INSERT INTO t1 (a00) VALUES ('db');
+INSERT INTO t1 (a00) VALUES ('dc');
+INSERT INTO t1 (a00) VALUES ('dd');
+INSERT INTO t1 (a00) VALUES ('de');
+INSERT INTO t1 (a00) VALUES ('df');
+INSERT INTO t1 (a00) VALUES ('dg');
+INSERT INTO t1 (a00) VALUES ('dh');
+INSERT INTO t1 (a00) VALUES ('di');
+INSERT INTO t1 (a00) VALUES ('dj');
+INSERT INTO t1 (a00) VALUES ('dk');
+INSERT INTO t1 (a00) VALUES ('dl');
+INSERT INTO t1 (a00) VALUES ('dm');
+INSERT INTO t1 (a00) VALUES ('dn');
+INSERT INTO t1 (a00) VALUES ('do');
+INSERT INTO t1 (a00) VALUES ('dp');
+INSERT INTO t1 (a00) VALUES ('dq');
+INSERT INTO t1 (a00) VALUES ('dr');
+INSERT INTO t1 (a00) VALUES ('ds');
+INSERT INTO t1 (a00) VALUES ('dt');
+INSERT INTO t1 (a00) VALUES ('du');
+INSERT INTO t1 (a00) VALUES ('dv');
+INSERT INTO t1 (a00) VALUES ('dw');
+INSERT INTO t1 (a00) VALUES ('dx');
+INSERT INTO t1 (a00) VALUES ('dy');
+INSERT INTO t1 (a00) VALUES ('dz');
+INSERT INTO t1 (a00) VALUES ('ea');
+INSERT INTO t1 (a00) VALUES ('eb');
+INSERT INTO t1 (a00) VALUES ('ec');
+INSERT INTO t1 (a00) VALUES ('ed');
+INSERT INTO t1 (a00) VALUES ('ee');
+INSERT INTO t1 (a00) VALUES ('ef');
+INSERT INTO t1 (a00) VALUES ('eg');
+INSERT INTO t1 (a00) VALUES ('eh');
+INSERT INTO t1 (a00) VALUES ('ei');
+INSERT INTO t1 (a00) VALUES ('ej');
+INSERT INTO t1 (a00) VALUES ('ek');
+INSERT INTO t1 (a00) VALUES ('el');
+ANALYZE TABLE t1;
+Table	Op	Msg_type	Msg_text
+test.t1	analyze	status	OK
+SELECT CLUST_INDEX_SIZE FROM information_schema.INNODB_SYS_TABLESTATS WHERE NAME = 'test/t1';
+CLUST_INDEX_SIZE
+23
+INSERT INTO t1 (a00) VALUES ('em');
+INSERT INTO t1 (a00) VALUES ('en');
+INSERT INTO t1 (a00) VALUES ('eo');
+INSERT INTO t1 (a00) VALUES ('ep');
+INSERT INTO t1 (a00) VALUES ('eq');
+INSERT INTO t1 (a00) VALUES ('er');
+INSERT INTO t1 (a00) VALUES ('es');
+INSERT INTO t1 (a00) VALUES ('et');
+INSERT INTO t1 (a00) VALUES ('eu');
+INSERT INTO t1 (a00) VALUES ('ev');
+INSERT INTO t1 (a00) VALUES ('ew');
+INSERT INTO t1 (a00) VALUES ('ex');
+INSERT INTO t1 (a00) VALUES ('ey');
+INSERT INTO t1 (a00) VALUES ('ez');
+INSERT INTO t1 (a00) VALUES ('fa');
+INSERT INTO t1 (a00) VALUES ('fb');
+INSERT INTO t1 (a00) VALUES ('fc');
+INSERT INTO t1 (a00) VALUES ('fd');
+INSERT INTO t1 (a00) VALUES ('fe');
+INSERT INTO t1 (a00) VALUES ('ff');
+INSERT INTO t1 (a00) VALUES ('fg');
+INSERT INTO t1 (a00) VALUES ('fh');
+INSERT INTO t1 (a00) VALUES ('fi');
+INSERT INTO t1 (a00) VALUES ('fj');
+INSERT INTO t1 (a00) VALUES ('fk');
+INSERT INTO t1 (a00) VALUES ('fl');
+INSERT INTO t1 (a00) VALUES ('fm');
+INSERT INTO t1 (a00) VALUES ('fn');
+INSERT INTO t1 (a00) VALUES ('fo');
+INSERT INTO t1 (a00) VALUES ('fp');
+INSERT INTO t1 (a00) VALUES ('fq');
+INSERT INTO t1 (a00) VALUES ('fr');
+INSERT INTO t1 (a00) VALUES ('fs');
+INSERT INTO t1 (a00) VALUES ('ft');
+INSERT INTO t1 (a00) VALUES ('fu');
+INSERT INTO t1 (a00) VALUES ('fv');
+INSERT INTO t1 (a00) VALUES ('fw');
+INSERT INTO t1 (a00) VALUES ('fx');
+INSERT INTO t1 (a00) VALUES ('fy');
+INSERT INTO t1 (a00) VALUES ('fz');
+INSERT INTO t1 (a00) VALUES ('ga');
+INSERT INTO t1 (a00) VALUES ('gb');
+INSERT INTO t1 (a00) VALUES ('gc');
+INSERT INTO t1 (a00) VALUES ('gd');
+INSERT INTO t1 (a00) VALUES ('ge');
+INSERT INTO t1 (a00) VALUES ('gf');
+INSERT INTO t1 (a00) VALUES ('gg');
+INSERT INTO t1 (a00) VALUES ('gh');
+ANALYZE TABLE t1;
+Table	Op	Msg_type	Msg_text
+test.t1	analyze	status	OK
+SELECT CLUST_INDEX_SIZE FROM information_schema.INNODB_SYS_TABLESTATS WHERE NAME = 'test/t1';
+CLUST_INDEX_SIZE
+29
+SET GLOBAL innodb_limit_optimistic_insert_debug = 0;
+# Test start
+SET DEBUG_SYNC = 'RESET';
+INSERT INTO t1 (a00) VALUES ('bfa');
+SET DEBUG_SYNC = 'before_insert_pessimitic_row_ins_clust SIGNAL reached WAIT_FOR continue';
+INSERT INTO t1 (a00) VALUES ('bfb');
+SET DEBUG_SYNC = 'now WAIT_FOR reached';
+SELECT a00,a01 FROM t1 WHERE a00 = 'aa';
+a00	a01
+aa	a
+SELECT a00,a01 FROM t1 WHERE a00 = 'aq';
+a00	a01
+aq	a
+SELECT a00,a01 FROM t1 WHERE a00 = 'cp';
+a00	a01
+cp	a
+SELECT a00,a01 FROM t1 WHERE a00 = 'el';
+a00	a01
+el	a
+SET DEBUG_SYNC = 'rw_s_lock_waiting SIGNAL lockwait1';
+SELECT a00,a01 FROM t1 WHERE a00 = 'ar';
+SET DEBUG_SYNC = 'rw_s_lock_waiting SIGNAL lockwait2';
+SELECT a00,a01 FROM t1 WHERE a00 = 'cn';
+SET DEBUG_SYNC = 'now WAIT_FOR lockwait1';
+SET DEBUG_SYNC = 'now WAIT_FOR lockwait2';
+SET DEBUG_SYNC = 'now SIGNAL continue';
+a00	a01
+ar	a
+a00	a01
+cn	a
+ANALYZE TABLE t1;
+Table	Op	Msg_type	Msg_text
+test.t1	analyze	status	OK
+SELECT CLUST_INDEX_SIZE FROM information_schema.INNODB_SYS_TABLESTATS WHERE NAME = 'test/t1';
+CLUST_INDEX_SIZE
+30
+SET DEBUG_SYNC = 'RESET';
+INSERT INTO t1 (a00) VALUES ('cva');
+SET DEBUG_SYNC = 'before_insert_pessimitic_row_ins_clust SIGNAL reached WAIT_FOR continue';
+INSERT INTO t1 (a00) VALUES ('cvb');
+SET DEBUG_SYNC = 'now WAIT_FOR reached';
+SET DEBUG_SYNC = 'rw_s_lock_waiting SIGNAL lockwait1';
+SELECT a00,a01 FROM t1 WHERE a00 = 'aa';
+SET DEBUG_SYNC = 'rw_s_lock_waiting SIGNAL lockwait2';
+SELECT a00,a01 FROM t1 WHERE a00 = 'el';
+SET DEBUG_SYNC = 'now WAIT_FOR lockwait1';
+SET DEBUG_SYNC = 'now WAIT_FOR lockwait2';
+SET DEBUG_SYNC = 'now SIGNAL continue';
+a00	a01
+aa	a
+a00	a01
+el	a
+ANALYZE TABLE t1;
+Table	Op	Msg_type	Msg_text
+test.t1	analyze	status	OK
+SELECT CLUST_INDEX_SIZE FROM information_schema.INNODB_SYS_TABLESTATS WHERE NAME = 'test/t1';
+CLUST_INDEX_SIZE
+31
+SET DEBUG_SYNC = 'RESET';
+INSERT INTO t1 (a00) VALUES ('gba');
+SET DEBUG_SYNC = 'before_insert_pessimitic_row_ins_clust SIGNAL reached WAIT_FOR continue';
+INSERT INTO t1 (a00) VALUES ('gbb');
+SET DEBUG_SYNC = 'now WAIT_FOR reached';
+SELECT a00,a01 FROM t1 WHERE a00 = 'aa';
+a00	a01
+aa	a
+SELECT a00,a01 FROM t1 WHERE a00 = 'ek';
+a00	a01
+ek	a
+SET DEBUG_SYNC = 'rw_s_lock_waiting SIGNAL lockwait1';
+SELECT a00,a01 FROM t1 WHERE a00 = 'el';
+SET DEBUG_SYNC = 'rw_s_lock_waiting SIGNAL lockwait2';
+SELECT a00,a01 FROM t1 WHERE a00 = 'gb';
+SET DEBUG_SYNC = 'now WAIT_FOR lockwait1';
+SET DEBUG_SYNC = 'now WAIT_FOR lockwait2';
+SET DEBUG_SYNC = 'now SIGNAL continue';
+a00	a01
+el	a
+a00	a01
+gb	a
+ANALYZE TABLE t1;
+Table	Op	Msg_type	Msg_text
+test.t1	analyze	status	OK
+SELECT CLUST_INDEX_SIZE FROM information_schema.INNODB_SYS_TABLESTATS WHERE NAME = 'test/t1';
+CLUST_INDEX_SIZE
+32
+SET DEBUG_SYNC = 'RESET';
+DROP TABLE t1;
diff --git a/mysql-test/suite/innodb/r/innodb_wl6326_big.result b/mysql-test/suite/innodb/r/innodb_wl6326_big.result
new file mode 100644
index 0000000..fc0b9c7
--- /dev/null
+++ b/mysql-test/suite/innodb/r/innodb_wl6326_big.result
@@ -0,0 +1,445 @@
+CREATE SCHEMA my_schema;
+USE my_schema;
+CREATE FUNCTION f_thread_id (i INT) RETURNS CHAR(4) DETERMINISTIC
+RETURN CONCAT(LPAD(CAST(i AS CHAR),3,'_'),'_') ;
+SELECT CONCAT('->', f_thread_id( 1), '<-');
+CONCAT('->', f_thread_id( 1), '<-')
+->__1_<-
+SELECT CONCAT('->', f_thread_id(12), '<-');
+CONCAT('->', f_thread_id(12), '<-')
+->_12_<-
+SET @extra_int    = 1;
+SET @extra_string = f_thread_id(1);
+SELECT @extra_int , @extra_string;
+ at extra_int	@extra_string
+1	__1_
+CREATE FUNCTION f_col_int1 (i INT) RETURNS INT(20) DETERMINISTIC
+RETURN i * 1000 + @extra_int ;
+SELECT f_col_int1(my_col) AS my_result
+FROM (SELECT 1 AS my_col UNION SELECT 12 UNION SELECT 123
+UNION SELECT 1234 UNION SELECT 12345) AS tx;
+my_result
+1001
+12001
+123001
+1234001
+12345001
+CREATE FUNCTION f_col_int2 (i INT) RETURNS INT(20) DETERMINISTIC
+RETURN @extra_int * 10000000 + i ;
+SELECT f_col_int2(my_col) AS my_result
+FROM (SELECT 1 AS my_col UNION SELECT 12 UNION SELECT 123
+UNION SELECT 1234 UNION SELECT 12345) AS tx;
+my_result
+10000001
+10000012
+10000123
+10001234
+10012345
+CREATE FUNCTION f_col_int3 (i INT) RETURNS INT(20) DETERMINISTIC
+RETURN @extra_int ;
+SELECT f_col_int3(my_col) AS my_result
+FROM (SELECT 1 AS my_col UNION SELECT 12 UNION SELECT 123
+UNION SELECT 1234 UNION SELECT 12345) AS tx;
+my_result
+1
+1
+1
+1
+1
+CREATE FUNCTION f_col_blob (i INT) RETURNS BLOB DETERMINISTIC
+RETURN RPAD(@extra_string,(@@innodb_page_size / 2 ) + 1,'a');
+SELECT CONCAT('->', f_col_blob(my_col), '<-') AS my_result
+FROM (SELECT 1 AS my_col UNION SELECT 12 UNION SELECT 123
+UNION SELECT 1234 UNION SELECT 12345) AS tx;
+my_result
+->__1_aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
 aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
 aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
 aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
 aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
 aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
 aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
 aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
 aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa<-
+->__1_aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
 aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
 aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
 aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
 aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
 aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
 aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
 aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
 aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa<-
+->__1_aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
 aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
 aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
 aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
 aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
 aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
 aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
 aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
 aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa<-
+->__1_aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
 aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
 aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
 aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
 aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
 aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
 aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
 aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
 aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa<-
+->__1_aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
 aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
 aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
 aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
 aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
 aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
 aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
 aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
 aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa<-
+CREATE FUNCTION f_col_char0 (i INT) RETURNS CHAR(255) DETERMINISTIC
+RETURN LPAD(CAST(i AS CHAR),255,' ');
+SELECT CONCAT('->', f_col_char0(my_col), '<-') AS my_result
+FROM (SELECT 1 AS my_col UNION SELECT 12 UNION SELECT 123
+UNION SELECT 1234 UNION SELECT 12345) AS tx;
+my_result
+->                                                                                                                                                                                                                                                              1<-
+->                                                                                                                                                                                                                                                             12<-
+->                                                                                                                                                                                                                                                            123<-
+->                                                                                                                                                                                                                                                           1234<-
+->                                                                                                                                                                                                                                                          12345<-
+CREATE FUNCTION f_col_char1 (i INT) RETURNS CHAR(26) DETERMINISTIC
+RETURN
+CONCAT('B',
+LPAD(SUBSTR(CAST(i AS CHAR),1,(LENGTH(CAST(i AS CHAR)) DIV 2)),10,' '),
+ at extra_string,
+RPAD(SUBSTR(CAST(i AS CHAR), -((LENGTH(CAST(i AS CHAR)) + 1) DIV 2)),10,' '),
+'E') ;
+SELECT CONCAT('->', f_col_char1(my_col), '<-') AS my_result
+FROM (SELECT 1 AS my_col UNION SELECT 12 UNION SELECT 123
+UNION SELECT 1234 UNION SELECT 12345) AS tx;
+my_result
+->B          __1_1         E<-
+->B         1__1_2         E<-
+->B         1__1_23        E<-
+->B        12__1_34        E<-
+->B        12__1_345       E<-
+CREATE FUNCTION f_col_char2 (i INT) RETURNS CHAR(26) DETERMINISTIC
+RETURN
+CONCAT('B',
+RPAD(SUBSTR(CAST(i AS CHAR),1,(LENGTH(CAST(i AS CHAR)) DIV 2)),10,' '),
+ at extra_string,
+LPAD(SUBSTR(CAST(i AS CHAR), -((LENGTH(CAST(i AS CHAR)) + 1) DIV 2)),10,' '),
+'E');
+SELECT CONCAT('->', f_col_char2(my_col), '<-') AS my_result
+FROM (SELECT 1 AS my_col UNION SELECT 12 UNION SELECT 123
+UNION SELECT 1234 UNION SELECT 12345) AS tx;
+my_result
+->B          __1_         1E<-
+->B1         __1_         2E<-
+->B1         __1_        23E<-
+->B12        __1_        34E<-
+->B12        __1_       345E<-
+CREATE FUNCTION f_col_char3 (i INT) RETURNS CHAR(26) DETERMINISTIC
+RETURN
+CONCAT('B', at extra_string,LPAD(CAST(i AS CHAR),20,' '),'E');
+SELECT CONCAT('->', f_col_char3(my_col), '<-') AS my_result
+FROM (SELECT 1 AS my_col UNION SELECT 12 UNION SELECT 123
+UNION SELECT 1234 UNION SELECT 12345) AS tx;
+my_result
+->B__1_                   1E<-
+->B__1_                  12E<-
+->B__1_                 123E<-
+->B__1_                1234E<-
+->B__1_               12345E<-
+CREATE FUNCTION f_col_char4 (i INT) RETURNS CHAR(26) DETERMINISTIC
+RETURN
+CONCAT('B',RPAD(CAST(i AS CHAR),20,' '), at extra_string,'E');
+SELECT CONCAT('->', f_col_char4(my_col), '<-') AS my_result
+FROM (SELECT 1 AS my_col UNION SELECT 12 UNION SELECT 123
+UNION SELECT 1234 UNION SELECT 12345) AS tx;
+my_result
+->B1                   __1_E<-
+->B12                  __1_E<-
+->B123                 __1_E<-
+->B1234                __1_E<-
+->B12345               __1_E<-
+CREATE TABLE my_metrics LIKE information_schema.innodb_metrics;
+ALTER TABLE my_metrics ADD COLUMN phase ENUM('after', 'before'),
+DROP COLUMN SUBSYSTEM, DROP COLUMN TYPE, DROP COLUMN COMMENT,
+ADD PRIMARY KEY (NAME,phase);
+CREATE TABLE t1 (
+col_int0 BIGINT,
+col_int1 BIGINT,
+col_int2 BIGINT,
+col_int3 BIGINT,
+col_blob BLOB,
+col_char0 VARCHAR(255),
+col_char1 VARCHAR(30),
+col_char2 VARCHAR(30),
+col_char3 VARCHAR(30),
+col_char4 VARCHAR(30)
+) ENGINE = InnoDB;
+ALTER TABLE t1 ADD UNIQUE KEY uidx_col_int0 (col_int0),
+ADD UNIQUE KEY uidx1 (col_int1, col_char0),
+ADD UNIQUE KEY uidx2 (col_int2, col_char0, col_int1),
+ADD UNIQUE KEY uidx3 (col_int3, col_int2, col_char0),
+ADD UNIQUE KEY uidx4 (col_char1, col_char0),
+ADD UNIQUE KEY uidx5 (col_char2, col_char0, col_char1),
+ADD UNIQUE KEY uidx6 (col_char3, col_char2, col_char0),
+ADD UNIQUE KEY uidx7 (col_int1, col_int2, col_int3, col_char4,
+col_char1, col_char2, col_char3, col_char0),
+ADD KEY idx8 (col_blob(10), col_char4);
+CREATE PROCEDURE proc_fill_t1 (max_row_count INT, load_unit INT)
+BEGIN
+DECLARE my_count INTEGER DEFAULT 0;
+DECLARE max_load_count INTEGER DEFAULT 0;
+DROP TABLE IF EXISTS t0;
+CREATE TEMPORARY TABLE t0 (col_int0 BIGINT, PRIMARY KEY(col_int0));
+WHILE (my_count < load_unit ) DO
+SET my_count = my_count + 1;
+INSERT INTO t0 SET col_int0 = my_count;
+END WHILE;
+SET max_load_count = (SELECT (max_row_count DIV load_unit) + 1 );
+SELECT COUNT(col_int0) INTO @val FROM t1;
+SET my_count = 0;
+REPEAT
+INSERT INTO t1 (col_int0, col_int1, col_int2, col_int3, col_blob,
+col_char0, col_char1, col_char2,col_char3,col_char4)
+SELECT col_int0 + @val,
+f_col_int1(col_int0 + @val),
+f_col_int2(col_int0 + @val),
+f_col_int3(col_int0 + @val),
+f_col_blob(col_int0 + @val),
+f_col_char0(col_int0 + @val),
+f_col_char1(col_int0 + @val),
+f_col_char2(col_int0 + @val),
+f_col_char3(col_int0 + @val),
+f_col_char4(col_int0 + @val)
+FROM t0;
+COMMIT;
+SELECT MAX(col_int0) INTO @val FROM t1;
+SET my_count = my_count + 1;
+UNTIL( my_count > max_load_count OR @val >= max_row_count )
+END REPEAT;
+DROP TEMPORARY TABLE t0;
+END|
+CREATE PROCEDURE proc_dml (max_duration INT, t1_stripe_half INT)
+BEGIN
+DECLARE aux INTEGER DEFAULT 0;
+DECLARE start_time INT;
+DECLARE CONTINUE HANDLER FOR SQLEXCEPTION, SQLWARNING, NOT FOUND BEGIN END;
+SET @extra_int    = CONNECTION_ID();
+SET @extra_string = f_thread_id(@extra_int);
+SELECT ROUND(MAX(col_int0) / 2 ) INTO @t1_half FROM t1;
+# The user lock 'Blocker' should be already set by some other session S1.
+# S1 starts the race by releasing that lock.
+# Wait till the lock is released and the lock can be obtained.
+# In order to prevent endless waiting in case of non foreseen problems
+# limit the timespan to 30 seconds.
+SELECT GET_LOCK('Blocker', 30) INTO @aux;
+# Release the lock immediate so that the other "runner" sessions start too.
+SELECT RELEASE_LOCK('Blocker') INTO @aux;
+SET start_time = UNIX_TIMESTAMP();
+WHILE (UNIX_TIMESTAMP() - start_time < max_duration) DO
+SET @aux = @t1_half - t1_stripe_half + ROUND(RAND() * t1_stripe_half * 2);
+UPDATE t1 SET
+col_int1  = f_col_int1(col_int0),
+col_int2  = f_col_int2(col_int0),
+col_int3  = f_col_int3(col_int0),
+col_blob  = f_col_blob(col_int0),
+col_char0 = f_col_char0(col_int0),
+col_char1 = f_col_char1(col_int0),
+col_char2 = f_col_char2(col_int0),
+col_char3 = f_col_char3(col_int0),
+col_char4 = f_col_char4(col_int0)
+WHERE col_int0 = @aux;
+COMMIT;
+END WHILE;
+END|
+SET GLOBAL innodb_monitor_disable = "innodb_rwlock_sx_%";
+SET @pre_reset_ts = NOW();
+SET GLOBAL innodb_monitor_reset   = "innodb_rwlock_sx_%";
+SET @pre_enable_ts = NOW();
+SET GLOBAL innodb_monitor_enable  = "innodb_rwlock_sx_%";
+SET @pre_collect_ts = NOW();
+DELETE FROM my_metrics;
+INSERT INTO my_metrics
+SELECT NAME, COUNT, MAX_COUNT, MIN_COUNT, AVG_COUNT,
+COUNT_RESET, MAX_COUNT_RESET, MIN_COUNT_RESET, AVG_COUNT_RESET,
+TIME_ENABLED, TIME_DISABLED, TIME_ELAPSED, TIME_RESET,
+STATUS, 'before'
+FROM information_schema.innodb_metrics
+WHERE NAME LIKE 'innodb_rwlock_sx_%';
+# TC-01 There are exact three entries "innodb_rwlock_sx_%" with the
+#       with the name which follow in innodb_metrics.
+#    pass
+SELECT COUNT(*) INTO @sx_count FROM my_metrics;
+# TC-02 Counting is now enabled. ALL = @sx_count entries show that.
+#    pass
+# TC-03 @pre_reset_ts < TIME_RESET. ALL = @sx_count entries show that.
+#    pass
+# TC-04 @pre_enable_ts < TIME_ENABLED. ALL = @sx_count entries show that.
+#    pass
+# TC-05 TIME_RESET < TIME_ENABLED AND TIME_ENABLED < @pre_collect_ts
+#       AND TIME_ELAPSED > 0. ALL = @sx_count entries show that.
+#    pass
+# TC-06 COUNT_RESET = MAX_COUNT_RESET. ALL = @sx_count entries show that.
+#    pass
+SET GLOBAL innodb_monitor_reset = "innodb_rwlock_sx_%";
+DELETE FROM my_metrics;
+INSERT INTO my_metrics
+SELECT NAME, COUNT, MAX_COUNT, MIN_COUNT, AVG_COUNT,
+COUNT_RESET, MAX_COUNT_RESET, MIN_COUNT_RESET, AVG_COUNT_RESET,
+TIME_ENABLED, TIME_DISABLED, TIME_ELAPSED, TIME_RESET,
+STATUS, 'before'
+FROM information_schema.innodb_metrics
+WHERE NAME LIKE 'innodb_rwlock_sx_%';
+SET @extra_string = '__0_';
+SET @extra_int    =    0;
+# TC-07 Insert some significant amount of rows into t1.
+#       The system MUST survive that.
+SET @max_row_count = <max_row_count>;
+SET @load_unit = <load_unit>;
+SET @start_time = UNIX_TIMESTAMP();
+SET AUTOCOMMIT = OFF;
+CALL proc_fill_t1 ( @max_row_count, @load_unit);
+#    pass
+SET AUTOCOMMIT = ON;
+SHOW ENGINE INNODB STATUS;
+SELECT col_int0, col_int1, col_int2, col_int3,
+CONCAT('->', col_blob,'<-') AS  col_blobx,
+CONCAT('->',col_char0,'<-') AS col_char0x,
+CONCAT('->',col_char1,'<-') AS col_char1x,
+CONCAT('->',col_char2,'<-') AS col_char2x,
+CONCAT('->',col_char3,'<-') AS col_char3x,
+CONCAT('->',col_char4,'<-') AS col_char4x
+FROM t1 WHERE col_int0 between 98 AND 102;
+col_int0	98
+col_int1	98000
+col_int2	98
+col_int3	0
+col_blobx	->__0_aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
 aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
 aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
 aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
 aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
 aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
 aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
 aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
 aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa<-
+col_char0x	->                                                                                                                                                                                                                                                             98<-
+col_char1x	->B         9__0_8         E<-
+col_char2x	->B9         __0_         8E<-
+col_char3x	->B__0_                  98E<-
+col_char4x	->B98                  __0_E<-
+col_int0	99
+col_int1	99000
+col_int2	99
+col_int3	0
+col_blobx	->__0_aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
 aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
 aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
 aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
 aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
 aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
 aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
 aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
 aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa<-
+col_char0x	->                                                                                                                                                                                                                                                             99<-
+col_char1x	->B         9__0_9         E<-
+col_char2x	->B9         __0_         9E<-
+col_char3x	->B__0_                  99E<-
+col_char4x	->B99                  __0_E<-
+col_int0	100
+col_int1	100000
+col_int2	100
+col_int3	0
+col_blobx	->__0_aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
 aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
 aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
 aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
 aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
 aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
 aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
 aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
 aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa<-
+col_char0x	->                                                                                                                                                                                                                                                            100<-
+col_char1x	->B         1__0_00        E<-
+col_char2x	->B1         __0_        00E<-
+col_char3x	->B__0_                 100E<-
+col_char4x	->B100                 __0_E<-
+col_int0	101
+col_int1	101000
+col_int2	101
+col_int3	0
+col_blobx	->__0_aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
 aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
 aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
 aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
 aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
 aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
 aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
 aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
 aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa<-
+col_char0x	->                                                                                                                                                                                                                                                            101<-
+col_char1x	->B         1__0_01        E<-
+col_char2x	->B1         __0_        01E<-
+col_char3x	->B__0_                 101E<-
+col_char4x	->B101                 __0_E<-
+col_int0	102
+col_int1	102000
+col_int2	102
+col_int3	0
+col_blobx	->__0_aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
 aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
 aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
 aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
 aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
 aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
 aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
 aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
 aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa<-
+col_char0x	->                                                                                                                                                                                                                                                            102<-
+col_char1x	->B         1__0_02        E<-
+col_char2x	->B1         __0_        02E<-
+col_char3x	->B__0_                 102E<-
+col_char4x	->B102                 __0_E<-
+INSERT INTO my_metrics
+SELECT NAME, COUNT, MAX_COUNT, MIN_COUNT, AVG_COUNT,
+COUNT_RESET, MAX_COUNT_RESET, MIN_COUNT_RESET, AVG_COUNT_RESET,
+TIME_ENABLED, TIME_DISABLED, TIME_ELAPSED, TIME_RESET,
+STATUS, 'after'
+FROM information_schema.innodb_metrics
+WHERE NAME LIKE 'innodb_rwlock_sx_%';
+# TC-8 There was a reset. COUNT_RESET = MAX_COUNT_RESET for ALL
+#      = @sx_count entries before activity.
+#    pass
+# TC-9 Heavy activity after reset.
+#      COUNT_RESET = MAX_COUNT_RESET for ALL = @sx_count entries.
+#    pass
+# TC-10 Heavy activity on sufficient big table + index structure after
+#       reset. COUNT_RESET grows for ALL = @sx_count entries.
+#    pass
+# TC-11 Let several concurrent users perform updates in t1 like mad.
+#       The system MUST survive this.
+#       Printing of statements is partially suppressed.
+SET GLOBAL innodb_monitor_reset = "innodb_rwlock_sx_%";
+DELETE FROM my_metrics;
+INSERT INTO my_metrics
+SELECT NAME, COUNT, MAX_COUNT, MIN_COUNT, AVG_COUNT,
+COUNT_RESET, MAX_COUNT_RESET, MIN_COUNT_RESET, AVG_COUNT_RESET,
+TIME_ENABLED, TIME_DISABLED, TIME_ELAPSED, TIME_RESET,
+STATUS, 'before'
+FROM information_schema.innodb_metrics
+WHERE NAME LIKE 'innodb_rwlock_sx_%';
+SET @start_time = UNIX_TIMESTAMP();
+SELECT 1 FROM t1 WHERE col_int0 = 5000 FOR UPDATE;
+1
+1
+SELECT GET_LOCK('Blocker', 1000) ;
+GET_LOCK('Blocker', 1000)
+1
+RELEASE_LOCK('Blocker')
+1
+#    pass
+INSERT INTO my_metrics
+SELECT NAME, COUNT, MAX_COUNT, MIN_COUNT, AVG_COUNT,
+COUNT_RESET, MAX_COUNT_RESET, MIN_COUNT_RESET, AVG_COUNT_RESET,
+TIME_ENABLED, TIME_DISABLED, TIME_ELAPSED, TIME_RESET,
+STATUS, 'after'
+FROM information_schema.innodb_metrics
+WHERE NAME LIKE 'innodb_rwlock_sx_%';
+SHOW ENGINE INNODB STATUS;
+# TC-12 Heavy activity on sufficient big table + index structure after
+#       reset. Several concurrent sessions were running updates.
+#       COUNT_RESET grows for ALL = @sx_count entries.
+#    pass
+# TC-13 The system MUST survive a ALTER TABLE t1 ADD KEY ... on
+#       the fat table t1.
+SET GLOBAL innodb_monitor_reset = "innodb_rwlock_sx_%";
+DELETE FROM my_metrics;
+INSERT INTO my_metrics
+SELECT NAME, COUNT, MAX_COUNT, MIN_COUNT, AVG_COUNT,
+COUNT_RESET, MAX_COUNT_RESET, MIN_COUNT_RESET, AVG_COUNT_RESET,
+TIME_ENABLED, TIME_DISABLED, TIME_ELAPSED, TIME_RESET,
+STATUS, 'before'
+FROM information_schema.innodb_metrics
+WHERE NAME LIKE 'innodb_rwlock_sx_%';
+SET @start_time = UNIX_TIMESTAMP();
+ALTER TABLE t1 ADD KEY idx_col_char4_col_char0 (col_char4,col_char0);
+INSERT INTO my_metrics
+SELECT NAME, COUNT, MAX_COUNT, MIN_COUNT, AVG_COUNT,
+COUNT_RESET, MAX_COUNT_RESET, MIN_COUNT_RESET, AVG_COUNT_RESET,
+TIME_ENABLED, TIME_DISABLED, TIME_ELAPSED, TIME_RESET,
+STATUS, 'after'
+FROM information_schema.innodb_metrics
+WHERE NAME LIKE 'innodb_rwlock_sx_%';
+#    pass
+SHOW ENGINE INNODB STATUS;
+# TC-14 The ADD KEY caused heavy activity on the sufficient big table.
+#       COUNT_RESET grows for ALL = @sx_count entries.
+#    pass
+# TC-15 The system MUST survive a fat update on the fat table t1.
+SET GLOBAL innodb_monitor_reset = "innodb_rwlock_sx_%";
+DELETE FROM my_metrics;
+INSERT INTO my_metrics
+SELECT NAME, COUNT, MAX_COUNT, MIN_COUNT, AVG_COUNT,
+COUNT_RESET, MAX_COUNT_RESET, MIN_COUNT_RESET, AVG_COUNT_RESET,
+TIME_ENABLED, TIME_DISABLED, TIME_ELAPSED, TIME_RESET,
+STATUS, 'before'
+FROM information_schema.innodb_metrics
+WHERE NAME LIKE 'innodb_rwlock_sx_%';
+SET @start_time   = UNIX_TIMESTAMP();
+SET @extra_int    = 13;
+SET @extra_string = f_thread_id(@extra_int);
+UPDATE t1 SET
+col_int1  = f_col_int1(col_int0),  col_int2  = f_col_int2(col_int0),
+col_int3  = f_col_int3(col_int0),  col_blob  = f_col_blob(col_int0),
+col_char0 = f_col_char0(col_int0), col_char1 = f_col_char1(col_int0),
+col_char2 = f_col_char2(col_int0), col_char3 = f_col_char3(col_int0),
+col_char4 = f_col_char4(col_int0)
+WHERE col_int0 BETWEEN 5000 - 2500 AND 5000 + 2500;
+COMMIT;
+INSERT INTO my_metrics
+SELECT NAME, COUNT, MAX_COUNT, MIN_COUNT, AVG_COUNT,
+COUNT_RESET, MAX_COUNT_RESET, MIN_COUNT_RESET, AVG_COUNT_RESET,
+TIME_ENABLED, TIME_DISABLED, TIME_ELAPSED, TIME_RESET,
+STATUS, 'after'
+FROM information_schema.innodb_metrics
+WHERE NAME LIKE 'innodb_rwlock_sx_%';
+SHOW ENGINE INNODB STATUS;
+#    pass
+# TC-16 The UPDATE caused heavy activity on the sufficient big table.
+#       COUNT_RESET grows for ALL = @sx_count entries.
+#    pass
+USE test;
+DROP SCHEMA my_schema;
+SET GLOBAL innodb_monitor_disable   = all;
+SET GLOBAL innodb_monitor_reset_all = all;
+SET GLOBAL innodb_monitor_enable    = default;
+SET GLOBAL innodb_monitor_disable   = default;
+SET GLOBAL innodb_monitor_reset     = default;
+SET GLOBAL innodb_monitor_reset_all = default;
+SET GLOBAL innodb_monitor_disable   = "innodb_rwlock_sx_%";
+SET GLOBAL innodb_monitor_reset     = "innodb_rwlock_sx_%";
diff --git a/mysql-test/suite/innodb/t/innodb_wl6326.opt b/mysql-test/suite/innodb/t/innodb_wl6326.opt
new file mode 100644
index 0000000..7301bc1
--- /dev/null
+++ b/mysql-test/suite/innodb/t/innodb_wl6326.opt
@@ -0,0 +1 @@
+--innodb-sys-tablestats=1
diff --git a/mysql-test/suite/innodb/t/innodb_wl6326.test b/mysql-test/suite/innodb/t/innodb_wl6326.test
new file mode 100644
index 0000000..7f4c542
--- /dev/null
+++ b/mysql-test/suite/innodb/t/innodb_wl6326.test
@@ -0,0 +1,500 @@
+#
+# WL#6326: InnoDB: fix index->lock contention
+#
+
+--source include/have_innodb.inc
+--source include/have_debug.inc
+--source include/have_debug_sync.inc
+--source include/have_innodb_16k.inc
+
+--disable_query_log
+SET @old_innodb_limit_optimistic_insert_debug = @@innodb_limit_optimistic_insert_debug;
+SET @old_innodb_adaptive_hash_index = @@innodb_adaptive_hash_index;
+SET @old_innodb_stats_persistent = @@innodb_stats_persistent;
+--enable_query_log
+--disable_warnings
+DROP TABLE IF EXISTS t1;
+--enable_warnings
+
+# Save the initial number of concurrent sessions
+--source include/count_sessions.inc
+
+SET GLOBAL innodb_adaptive_hash_index = false;
+SET GLOBAL innodb_stats_persistent = false;
+
+--connect (con1,localhost,root,,)
+--connect (con2,localhost,root,,)
+--connect (con3,localhost,root,,)
+
+CREATE TABLE t1 (
+  a00 CHAR(255) NOT NULL DEFAULT 'a',
+  a01 CHAR(255) NOT NULL DEFAULT 'a',
+  a02 CHAR(255) NOT NULL DEFAULT 'a',
+  a03 CHAR(255) NOT NULL DEFAULT 'a',
+  a04 CHAR(255) NOT NULL DEFAULT 'a',
+  a05 CHAR(255) NOT NULL DEFAULT 'a',
+  a06 CHAR(255) NOT NULL DEFAULT 'a',
+  b INT NOT NULL DEFAULT 0
+) ENGINE = InnoDB;
+
+ALTER TABLE t1 ADD CONSTRAINT pkey PRIMARY KEY(
+  a00,
+  a01,
+  a02,
+  a03,
+  a04,
+  a05,
+  a06
+);
+
+#
+# Prepare primary key index tree to be used for this test.
+#
+
+# Only root (1)
+ANALYZE TABLE t1;
+SELECT CLUST_INDEX_SIZE FROM information_schema.INNODB_SYS_TABLESTATS WHERE NAME = 'test/t1';
+
+# Make the first records sparse artificially,
+# not to cause modify_tree by single node_ptr insert operation.
+# * (7 - 2) records should be larger than a half of the page size
+# * (7 + 2) records should be fit to the page
+# (above t1 definition is already adjusted)
+SET GLOBAL innodb_limit_optimistic_insert_debug = 7;
+
+INSERT INTO t1 (a00) VALUES ('aa');
+INSERT INTO t1 (a00) VALUES ('ab');
+INSERT INTO t1 (a00) VALUES ('ac');
+INSERT INTO t1 (a00) VALUES ('ad');
+INSERT INTO t1 (a00) VALUES ('ae');
+INSERT INTO t1 (a00) VALUES ('af');
+INSERT INTO t1 (a00) VALUES ('ag');
+INSERT INTO t1 (a00) VALUES ('ah');
+# Raise root (1-2)
+# (aa,ad)
+# (aa,ab,ac)(ad,ae,af,ag,ah)
+ANALYZE TABLE t1;
+SELECT CLUST_INDEX_SIZE FROM information_schema.INNODB_SYS_TABLESTATS WHERE NAME = 'test/t1';
+
+INSERT INTO t1 (a00) VALUES ('ai');
+INSERT INTO t1 (a00) VALUES ('aj');
+INSERT INTO t1 (a00) VALUES ('ak');
+# Split leaf (1-3)
+# (aa,ad,ak)
+# (aa,ab,ac)(ad,ae,af,ag,ah,ai,aj)(ak)
+ANALYZE TABLE t1;
+SELECT CLUST_INDEX_SIZE FROM information_schema.INNODB_SYS_TABLESTATS WHERE NAME = 'test/t1';
+
+INSERT INTO t1 (a00) VALUES ('al');
+INSERT INTO t1 (a00) VALUES ('am');
+INSERT INTO t1 (a00) VALUES ('an');
+INSERT INTO t1 (a00) VALUES ('ao');
+INSERT INTO t1 (a00) VALUES ('ap');
+INSERT INTO t1 (a00) VALUES ('aq');
+INSERT INTO t1 (a00) VALUES ('ar');
+# Split leaf (1-4)
+# (aa,ad,ak,ar)
+# (aa,ab,ac)(ad,ae,af,ag,ah,ai,aj)(ak,al,am,an,ao,ap,aq)(ar)
+ANALYZE TABLE t1;
+SELECT CLUST_INDEX_SIZE FROM information_schema.INNODB_SYS_TABLESTATS WHERE NAME = 'test/t1';
+
+INSERT INTO t1 (a00) VALUES ('as');
+INSERT INTO t1 (a00) VALUES ('at');
+INSERT INTO t1 (a00) VALUES ('au');
+INSERT INTO t1 (a00) VALUES ('av');
+INSERT INTO t1 (a00) VALUES ('aw');
+INSERT INTO t1 (a00) VALUES ('ax');
+INSERT INTO t1 (a00) VALUES ('ay');
+# Split leaf (1-5)
+# (aa,ad,ak,ar,ay)
+# (aa,ab,ac)(ad,ae,af,ag,ah,ai,aj)(ak,al,am,an,ao,ap,aq)(ar,as,at,au,av,aw,ax)(ay)
+ANALYZE TABLE t1;
+SELECT CLUST_INDEX_SIZE FROM information_schema.INNODB_SYS_TABLESTATS WHERE NAME = 'test/t1';
+
+INSERT INTO t1 (a00) VALUES ('az');
+INSERT INTO t1 (a00) VALUES ('ba');
+INSERT INTO t1 (a00) VALUES ('bb');
+INSERT INTO t1 (a00) VALUES ('bc');
+INSERT INTO t1 (a00) VALUES ('bd');
+INSERT INTO t1 (a00) VALUES ('be');
+INSERT INTO t1 (a00) VALUES ('bf');
+# Split leaf (1-6)
+# (aa,ad,ak,ar,ay,bf)
+# (aa,ab,ac)(ad..)(ak..)(ar,as,at,au,av,aw,ax)(ay,az,ba,bb,bc,bd,be)(bf)
+ANALYZE TABLE t1;
+SELECT CLUST_INDEX_SIZE FROM information_schema.INNODB_SYS_TABLESTATS WHERE NAME = 'test/t1';
+
+
+INSERT INTO t1 (a00) VALUES ('bg');
+INSERT INTO t1 (a00) VALUES ('bh');
+INSERT INTO t1 (a00) VALUES ('bi');
+INSERT INTO t1 (a00) VALUES ('bj');
+INSERT INTO t1 (a00) VALUES ('bk');
+INSERT INTO t1 (a00) VALUES ('bl');
+INSERT INTO t1 (a00) VALUES ('bm');
+# Split leaf (1-7)
+# (aa,ad,ak,ar,ay,bf,bm)
+# (aa,ab,ac)(ad..)(ak..)(ar..)(ay,az,ba,bb,bc,bd,be)(bf,bg,bh,bi,bj,bk,bl)(bm)
+ANALYZE TABLE t1;
+SELECT CLUST_INDEX_SIZE FROM information_schema.INNODB_SYS_TABLESTATS WHERE NAME = 'test/t1';
+
+INSERT INTO t1 (a00) VALUES ('bn');
+INSERT INTO t1 (a00) VALUES ('bo');
+INSERT INTO t1 (a00) VALUES ('bp');
+INSERT INTO t1 (a00) VALUES ('bq');
+INSERT INTO t1 (a00) VALUES ('br');
+INSERT INTO t1 (a00) VALUES ('bs');
+INSERT INTO t1 (a00) VALUES ('bt');
+# Raise root (1-2-8)
+# (aa,ar)
+# (aa,ad,ak)            (ar,ay,bf,bm,bt)
+# (aa,ab,ac)(ad..)(ak..)(ar..)(ay..)(bf..)(bm..)(bt)
+ANALYZE TABLE t1;
+SELECT CLUST_INDEX_SIZE FROM information_schema.INNODB_SYS_TABLESTATS WHERE NAME = 'test/t1';
+
+
+INSERT INTO t1 (a00) VALUES ('bu');
+INSERT INTO t1 (a00) VALUES ('bv');
+INSERT INTO t1 (a00) VALUES ('bw');
+INSERT INTO t1 (a00) VALUES ('bx');
+INSERT INTO t1 (a00) VALUES ('by');
+INSERT INTO t1 (a00) VALUES ('bz');
+INSERT INTO t1 (a00) VALUES ('ca');
+
+INSERT INTO t1 (a00) VALUES ('cb');
+INSERT INTO t1 (a00) VALUES ('cc');
+INSERT INTO t1 (a00) VALUES ('cd');
+INSERT INTO t1 (a00) VALUES ('ce');
+INSERT INTO t1 (a00) VALUES ('cf');
+INSERT INTO t1 (a00) VALUES ('cg');
+INSERT INTO t1 (a00) VALUES ('ch');
+
+INSERT INTO t1 (a00) VALUES ('ci');
+INSERT INTO t1 (a00) VALUES ('cj');
+INSERT INTO t1 (a00) VALUES ('ck');
+INSERT INTO t1 (a00) VALUES ('cl');
+INSERT INTO t1 (a00) VALUES ('cm');
+INSERT INTO t1 (a00) VALUES ('cn');
+INSERT INTO t1 (a00) VALUES ('co');
+# Split also at level 1 (1-3-11)
+# (aa,ar,co)
+# (aa,ad,ak)            (ar,ay,bf,bm,bt,ca,ch)                    (co)
+# (aa,ab,ac)(ad..)(ak..)(ar..)(ay..)(bf..)(bm..)(bt..)(ca..)(ch..)(co)
+ANALYZE TABLE t1;
+SELECT CLUST_INDEX_SIZE FROM information_schema.INNODB_SYS_TABLESTATS WHERE NAME = 'test/t1';
+
+
+INSERT INTO t1 (a00) VALUES ('cp');
+INSERT INTO t1 (a00) VALUES ('cq');
+INSERT INTO t1 (a00) VALUES ('cr');
+INSERT INTO t1 (a00) VALUES ('cs');
+INSERT INTO t1 (a00) VALUES ('ct');
+INSERT INTO t1 (a00) VALUES ('cu');
+INSERT INTO t1 (a00) VALUES ('cv');
+
+INSERT INTO t1 (a00) VALUES ('cw');
+INSERT INTO t1 (a00) VALUES ('cx');
+INSERT INTO t1 (a00) VALUES ('cy');
+INSERT INTO t1 (a00) VALUES ('cz');
+INSERT INTO t1 (a00) VALUES ('da');
+INSERT INTO t1 (a00) VALUES ('db');
+INSERT INTO t1 (a00) VALUES ('dc');
+
+INSERT INTO t1 (a00) VALUES ('dd');
+INSERT INTO t1 (a00) VALUES ('de');
+INSERT INTO t1 (a00) VALUES ('df');
+INSERT INTO t1 (a00) VALUES ('dg');
+INSERT INTO t1 (a00) VALUES ('dh');
+INSERT INTO t1 (a00) VALUES ('di');
+INSERT INTO t1 (a00) VALUES ('dj');
+
+INSERT INTO t1 (a00) VALUES ('dk');
+INSERT INTO t1 (a00) VALUES ('dl');
+INSERT INTO t1 (a00) VALUES ('dm');
+INSERT INTO t1 (a00) VALUES ('dn');
+INSERT INTO t1 (a00) VALUES ('do');
+INSERT INTO t1 (a00) VALUES ('dp');
+INSERT INTO t1 (a00) VALUES ('dq');
+
+INSERT INTO t1 (a00) VALUES ('dr');
+INSERT INTO t1 (a00) VALUES ('ds');
+INSERT INTO t1 (a00) VALUES ('dt');
+INSERT INTO t1 (a00) VALUES ('du');
+INSERT INTO t1 (a00) VALUES ('dv');
+INSERT INTO t1 (a00) VALUES ('dw');
+INSERT INTO t1 (a00) VALUES ('dx');
+
+INSERT INTO t1 (a00) VALUES ('dy');
+INSERT INTO t1 (a00) VALUES ('dz');
+INSERT INTO t1 (a00) VALUES ('ea');
+INSERT INTO t1 (a00) VALUES ('eb');
+INSERT INTO t1 (a00) VALUES ('ec');
+INSERT INTO t1 (a00) VALUES ('ed');
+INSERT INTO t1 (a00) VALUES ('ee');
+
+INSERT INTO t1 (a00) VALUES ('ef');
+INSERT INTO t1 (a00) VALUES ('eg');
+INSERT INTO t1 (a00) VALUES ('eh');
+INSERT INTO t1 (a00) VALUES ('ei');
+INSERT INTO t1 (a00) VALUES ('ej');
+INSERT INTO t1 (a00) VALUES ('ek');
+INSERT INTO t1 (a00) VALUES ('el');
+# Split also at level 1 (1-4-18)
+# (aa,ar,co,el)
+# (aa,ad,ak)            (ar,ay,bf,bm,bt,ca,ch)                    (co,cv,dc,dj,dq,dx,ee)                    (el)
+# (aa,ab,ac)(ad..)(ak..)(ar..)(ay..)(bf..)(bm..)(bt..)(ca..)(ch..)(co..)(cv..)(dc..)(dj..)(dq..)(dx..)(ee..)(el)
+ANALYZE TABLE t1;
+SELECT CLUST_INDEX_SIZE FROM information_schema.INNODB_SYS_TABLESTATS WHERE NAME = 'test/t1';
+
+INSERT INTO t1 (a00) VALUES ('em');
+INSERT INTO t1 (a00) VALUES ('en');
+INSERT INTO t1 (a00) VALUES ('eo');
+INSERT INTO t1 (a00) VALUES ('ep');
+INSERT INTO t1 (a00) VALUES ('eq');
+INSERT INTO t1 (a00) VALUES ('er');
+INSERT INTO t1 (a00) VALUES ('es');
+
+INSERT INTO t1 (a00) VALUES ('et');
+INSERT INTO t1 (a00) VALUES ('eu');
+INSERT INTO t1 (a00) VALUES ('ev');
+INSERT INTO t1 (a00) VALUES ('ew');
+INSERT INTO t1 (a00) VALUES ('ex');
+INSERT INTO t1 (a00) VALUES ('ey');
+INSERT INTO t1 (a00) VALUES ('ez');
+
+INSERT INTO t1 (a00) VALUES ('fa');
+INSERT INTO t1 (a00) VALUES ('fb');
+INSERT INTO t1 (a00) VALUES ('fc');
+INSERT INTO t1 (a00) VALUES ('fd');
+INSERT INTO t1 (a00) VALUES ('fe');
+INSERT INTO t1 (a00) VALUES ('ff');
+INSERT INTO t1 (a00) VALUES ('fg');
+
+INSERT INTO t1 (a00) VALUES ('fh');
+INSERT INTO t1 (a00) VALUES ('fi');
+INSERT INTO t1 (a00) VALUES ('fj');
+INSERT INTO t1 (a00) VALUES ('fk');
+INSERT INTO t1 (a00) VALUES ('fl');
+INSERT INTO t1 (a00) VALUES ('fm');
+INSERT INTO t1 (a00) VALUES ('fn');
+
+INSERT INTO t1 (a00) VALUES ('fo');
+INSERT INTO t1 (a00) VALUES ('fp');
+INSERT INTO t1 (a00) VALUES ('fq');
+INSERT INTO t1 (a00) VALUES ('fr');
+INSERT INTO t1 (a00) VALUES ('fs');
+INSERT INTO t1 (a00) VALUES ('ft');
+INSERT INTO t1 (a00) VALUES ('fu');
+
+INSERT INTO t1 (a00) VALUES ('fv');
+INSERT INTO t1 (a00) VALUES ('fw');
+INSERT INTO t1 (a00) VALUES ('fx');
+INSERT INTO t1 (a00) VALUES ('fy');
+INSERT INTO t1 (a00) VALUES ('fz');
+INSERT INTO t1 (a00) VALUES ('ga');
+INSERT INTO t1 (a00) VALUES ('gb');
+
+INSERT INTO t1 (a00) VALUES ('gc');
+INSERT INTO t1 (a00) VALUES ('gd');
+INSERT INTO t1 (a00) VALUES ('ge');
+INSERT INTO t1 (a00) VALUES ('gf');
+INSERT INTO t1 (a00) VALUES ('gg');
+INSERT INTO t1 (a00) VALUES ('gh');
+
+
+# Current tree form (1-4-24)
+# (aa,ar,co,el)
+# (aa,ad,ak)            (ar,ay,bf,bm,bt,ca,ch)                    (co,cv,dc,dj,dq,dx,ee)                    (el..,gb)
+# (aa,ab,ac)(ad..)(ak..)(ar..)(ay..)(bf..)(bm..)(bt..)(ca..)(ch..)(co..)(cv..)(dc..)(dj..)(dq..)(dx..)(ee..)(el..)..(gb..)
+ANALYZE TABLE t1;
+SELECT CLUST_INDEX_SIZE FROM information_schema.INNODB_SYS_TABLESTATS WHERE NAME = 'test/t1';
+
+
+
+# Insert the rest of records normally
+SET GLOBAL innodb_limit_optimistic_insert_debug = 0;
+
+
+--echo # Test start
+
+# (1) Insert records to leaf page (bf..) and cause modify_page.
+#     - root page is not X latched
+#     - latched from level 1 page (ar,ay,bf,bm,bt,ca,ch)
+
+SET DEBUG_SYNC = 'RESET';
+
+# Filling leaf page (bf..)
+INSERT INTO t1 (a00) VALUES ('bfa');
+
+--connection con1
+SET DEBUG_SYNC = 'before_insert_pessimitic_row_ins_clust SIGNAL reached WAIT_FOR continue';
+# Cause modify_tree
+--send
+INSERT INTO t1 (a00) VALUES ('bfb');
+
+--connection con2
+SET DEBUG_SYNC = 'now WAIT_FOR reached';
+# Not blocked searches
+SELECT a00,a01 FROM t1 WHERE a00 = 'aa';
+SELECT a00,a01 FROM t1 WHERE a00 = 'aq';
+# "where a00 = 'co'" is blocked because searching from smaller ('co','a','a',..).
+SELECT a00,a01 FROM t1 WHERE a00 = 'cp';
+SELECT a00,a01 FROM t1 WHERE a00 = 'el';
+
+SET DEBUG_SYNC = 'rw_s_lock_waiting SIGNAL lockwait1';
+# Blocked
+--send
+SELECT a00,a01 FROM t1 WHERE a00 = 'ar';
+
+--connection con3
+SET DEBUG_SYNC = 'rw_s_lock_waiting SIGNAL lockwait2';
+# Blocked
+--send
+SELECT a00,a01 FROM t1 WHERE a00 = 'cn';
+
+--connection default
+SET DEBUG_SYNC = 'now WAIT_FOR lockwait1';
+SET DEBUG_SYNC = 'now WAIT_FOR lockwait2';
+SET DEBUG_SYNC = 'now SIGNAL continue';
+
+--connection con1
+--reap
+
+--connection con2
+--reap
+
+--connection con3
+--reap
+
+--connection default
+
+ANALYZE TABLE t1;
+SELECT CLUST_INDEX_SIZE FROM information_schema.INNODB_SYS_TABLESTATS WHERE NAME = 'test/t1';
+
+
+
+# (2) Insert records to leaf page (cv..) and cause modify_page
+#     - root page is X latched, because node_ptr for 'cv'
+#       is 2nd record for (co,cv,dc,dj,dq,dx,ee)
+#
+# * ordinary pessimitic insert might be done by pessistic update
+#   and we should consider possibility node_ptr to be deleted.
+
+SET DEBUG_SYNC = 'RESET';
+
+# Filling leaf page (cv..)
+INSERT INTO t1 (a00) VALUES ('cva');
+
+--connection con1
+SET DEBUG_SYNC = 'before_insert_pessimitic_row_ins_clust SIGNAL reached WAIT_FOR continue';
+# Cause modify_tree
+--send
+INSERT INTO t1 (a00) VALUES ('cvb');
+
+--connection con2
+SET DEBUG_SYNC = 'now WAIT_FOR reached';
+# All searches are blocked because root page is X latched
+
+SET DEBUG_SYNC = 'rw_s_lock_waiting SIGNAL lockwait1';
+# Blocked
+--send
+SELECT a00,a01 FROM t1 WHERE a00 = 'aa';
+
+--connection con3
+SET DEBUG_SYNC = 'rw_s_lock_waiting SIGNAL lockwait2';
+# Blocked
+--send
+SELECT a00,a01 FROM t1 WHERE a00 = 'el';
+
+--connection default
+SET DEBUG_SYNC = 'now WAIT_FOR lockwait1';
+SET DEBUG_SYNC = 'now WAIT_FOR lockwait2';
+SET DEBUG_SYNC = 'now SIGNAL continue';
+
+--connection con1
+--reap
+
+--connection con2
+--reap
+
+--connection con3
+--reap
+
+--connection default
+
+ANALYZE TABLE t1;
+SELECT CLUST_INDEX_SIZE FROM information_schema.INNODB_SYS_TABLESTATS WHERE NAME = 'test/t1';
+
+
+
+# (3) Insert records to rightmost leaf page (gb..) and cause modify_page
+#     - root page is not X latched, because node_ptr for 'gb' is the last record
+#       of the level 1 though it is last record in the page.
+#     - lathed from level 1 page (el..,gb)
+
+SET DEBUG_SYNC = 'RESET';
+
+# Filling leaf page (gb..)
+INSERT INTO t1 (a00) VALUES ('gba');
+
+--connection con1
+SET DEBUG_SYNC = 'before_insert_pessimitic_row_ins_clust SIGNAL reached WAIT_FOR continue';
+# Cause modify_tree
+--send
+INSERT INTO t1 (a00) VALUES ('gbb');
+
+--connection con2
+SET DEBUG_SYNC = 'now WAIT_FOR reached';
+# Not blocked searches
+SELECT a00,a01 FROM t1 WHERE a00 = 'aa';
+SELECT a00,a01 FROM t1 WHERE a00 = 'ek';
+
+SET DEBUG_SYNC = 'rw_s_lock_waiting SIGNAL lockwait1';
+# Blocked
+--send
+SELECT a00,a01 FROM t1 WHERE a00 = 'el';
+
+--connection con3
+SET DEBUG_SYNC = 'rw_s_lock_waiting SIGNAL lockwait2';
+# Blocked
+--send
+SELECT a00,a01 FROM t1 WHERE a00 = 'gb';
+
+--connection default
+SET DEBUG_SYNC = 'now WAIT_FOR lockwait1';
+SET DEBUG_SYNC = 'now WAIT_FOR lockwait2';
+SET DEBUG_SYNC = 'now SIGNAL continue';
+
+--connection con1
+--reap
+
+--connection con2
+--reap
+
+--connection con3
+--reap
+
+--connection default
+ANALYZE TABLE t1;
+SELECT CLUST_INDEX_SIZE FROM information_schema.INNODB_SYS_TABLESTATS WHERE NAME = 'test/t1';
+
+
+
+# Cleanup
+SET DEBUG_SYNC = 'RESET';
+
+--connection default
+--disconnect con1
+--disconnect con2
+--disconnect con3
+
+DROP TABLE t1;
+
+--disable_query_log
+SET GLOBAL innodb_limit_optimistic_insert_debug = @old_innodb_limit_optimistic_insert_debug;
+SET GLOBAL innodb_adaptive_hash_index = @old_innodb_adaptive_hash_index;
+SET GLOBAL innodb_stats_persistent = @old_innodb_stats_persistent;
+--enable_query_log
+
+# Wait till all disconnects are completed.
+--source include/wait_until_count_sessions.inc
diff --git a/mysql-test/suite/innodb/t/innodb_wl6326_big.test b/mysql-test/suite/innodb/t/innodb_wl6326_big.test
new file mode 100644
index 0000000..ef9fed5
--- /dev/null
+++ b/mysql-test/suite/innodb/t/innodb_wl6326_big.test
@@ -0,0 +1,696 @@
+# This is a script for MTR with hybrid use.
+# a) As regression test
+#    Mostly some brute force attempt to stress the internal sx locks of
+#    InnoDB which were introduced by WL#6326+WL#6363.
+#    The file with expected results fits to this variant.
+#    The impact on code coverage is quite good.
+#    $max_row_count == 10000 means "Run variant a)".
+#    The file with expected results fits only to this variant.
+# b) As testbed for attempts to extend or improve the RQG test wl6326_sql.yy.
+#    1. The MTR based test uses
+#       - a table t1 with the same layout
+#       - the same stored functions
+#       - the same stored procedure proc_fill_t1 for inserting a configurable
+#         amount of records into t1
+#       like the RQG test wl6326_sql.yy.
+#    2. As soon as
+#          $max_row_count != 10000
+#       is fulfilled the variant b) will be executed.
+#       This variant produces debug output.
+#    The file with expected results fits only partially to this variant and
+#    it is to be expected that MTR reports "[ fail ]" because
+#    - test log and file with expected results differ
+#    - the test does not remove the file <$max_row_count>.out.
+
+# WL#6326 is about the sx locks (InnoDB feature only).
+--source include/have_innodb.inc
+# Runtime properties:
+# Notebook i5 dual core with HT, MySQL binaries compiled with debug,
+#          max_row_count=10000 rows
+# vardir on tmpfs : ~ 375
+# vardir on disk  : ~ 546
+--source include/big_test.inc
+# We go with "--send" and "--reap" and that fails with the embedded server.
+--source include/not_embedded.inc
+# Its intentional to not take the risk that a run with valgrind times out.
+--source include/not_valgrind.inc
+
+# FIXME:
+#    Increase the code coverage provided by the current test by
+#    trying "InnoDB Tablespace Monitor" as soon as some bug is fixed
+#    or wait till the deprecated "InnoDB Tablespace Monitor" is
+#    removed.
+
+# Setup of some parameters
+# ------------------------
+# Number of records within every chunk to be added to t1.
+let $load_unit= 10000;
+#
+# Rough number of records in t1 to achieve.
+#    We add chunks of $load_unit rows till the actual number
+#    of rows in the table t1 exceeds $max_row_count.
+# let $max_row_count= 1000000;
+# let $max_row_count= 300000;
+  let $max_row_count= 10000;        # ~ 322s  on tmpfs (NB)
+# let $max_row_count= 30000;
+# let $max_row_count= 100000;
+#
+# Determine which variant to run.
+let $test_debug= 0;
+if ($max_row_count != 10000)
+{
+   --echo # Execution for producing a DATALOAD file for RQG.
+   --echo # Result set diffs are to be expected.
+   let $test_debug= 1;
+}
+#
+# In case you want debug output though $max_row_count = 10000 is fulfilled
+# than set $test_debug to 1
+# let $test_debug= 1;
+#
+# Number of concurrent sessions to be used in the high load test.
+let $max_con=            10;
+# Duration of the high load test in seconds.
+let $high_load_duration= 60;
+
+
+
+# Putting all objects into the SCHEMA my_schema makes the final cleanup easier.
+# We simply run than DROP SCHEMA my_schema.
+CREATE SCHEMA my_schema;
+USE my_schema;
+CREATE FUNCTION f_thread_id (i INT) RETURNS CHAR(4) DETERMINISTIC
+RETURN CONCAT(LPAD(CAST(i AS CHAR),3,'_'),'_') ;
+SELECT CONCAT('->', f_thread_id( 1), '<-');
+SELECT CONCAT('->', f_thread_id(12), '<-');
+
+# Definition of parameters used in functions.
+# We use here a "1" in order to make the impact on the results of the functions
+# good visible.
+let $val= 1;
+eval SET @extra_int    = $val;
+eval SET @extra_string = f_thread_id($val);
+SELECT @extra_int , @extra_string;
+
+# The different functions are used later when filling t1 and also during
+# RQG testing. They serve to generate the difference between column values
+# in different rows in different areas of the column.
+# Fictional example:
+#    row 1 col_int0=1 colx='1abcdefgh' coly='abcd1efgh' colz='abcdefgh1'
+#    row 2 col_int0=2 colx='2abcdefgh' coly='abcd2efgh' colz='abcdefgh2'
+# The function f_<pattern> is for the column with the name <pattern>.
+# There is a function
+# - for every column except col_int0
+# - even if the SQL statement is simple.
+# The reason for this is the architecture of the RQG test.
+
+let $part= AS my_result
+FROM (SELECT 1 AS my_col UNION SELECT 12 UNION SELECT 123
+UNION SELECT 1234 UNION SELECT 12345) AS tx;
+
+let $function_name= f_col_int1;
+eval CREATE FUNCTION $function_name (i INT) RETURNS INT(20) DETERMINISTIC
+RETURN i * 1000 + @extra_int ;
+eval SELECT $function_name(my_col) $part;
+
+let $function_name= f_col_int2;
+eval CREATE FUNCTION $function_name (i INT) RETURNS INT(20) DETERMINISTIC
+RETURN @extra_int * 10000000 + i ;
+eval SELECT $function_name(my_col) $part;
+
+let $function_name= f_col_int3;
+eval CREATE FUNCTION $function_name (i INT) RETURNS INT(20) DETERMINISTIC
+RETURN @extra_int ;
+eval SELECT $function_name(my_col) $part;
+
+let $function_name= f_col_blob;
+eval CREATE FUNCTION $function_name (i INT) RETURNS BLOB DETERMINISTIC
+RETURN RPAD(@extra_string,(@@innodb_page_size / 2 ) + 1,'a');
+eval SELECT CONCAT('->', $function_name(my_col), '<-') $part;
+
+let $function_name= f_col_char0;
+eval CREATE FUNCTION $function_name (i INT) RETURNS CHAR(255) DETERMINISTIC
+RETURN LPAD(CAST(i AS CHAR),255,' ');
+eval SELECT CONCAT('->', $function_name(my_col), '<-') $part;
+
+let $function_name= f_col_char1;
+eval CREATE FUNCTION $function_name (i INT) RETURNS CHAR(26) DETERMINISTIC
+RETURN
+CONCAT('B',
+   LPAD(SUBSTR(CAST(i AS CHAR),1,(LENGTH(CAST(i AS CHAR)) DIV 2)),10,' '),
+   @extra_string,
+   RPAD(SUBSTR(CAST(i AS CHAR), -((LENGTH(CAST(i AS CHAR)) + 1) DIV 2)),10,' '),
+   'E') ;
+eval SELECT CONCAT('->', $function_name(my_col), '<-') $part;
+
+let $function_name= f_col_char2;
+eval CREATE FUNCTION $function_name (i INT) RETURNS CHAR(26) DETERMINISTIC
+RETURN
+CONCAT('B',
+   RPAD(SUBSTR(CAST(i AS CHAR),1,(LENGTH(CAST(i AS CHAR)) DIV 2)),10,' '),
+   @extra_string,
+   LPAD(SUBSTR(CAST(i AS CHAR), -((LENGTH(CAST(i AS CHAR)) + 1) DIV 2)),10,' '),
+   'E');
+eval SELECT CONCAT('->', $function_name(my_col), '<-') $part;
+
+let $function_name= f_col_char3;
+eval CREATE FUNCTION $function_name (i INT) RETURNS CHAR(26) DETERMINISTIC
+RETURN
+CONCAT('B', at extra_string,LPAD(CAST(i AS CHAR),20,' '),'E');
+eval SELECT CONCAT('->', $function_name(my_col), '<-') $part;
+
+let $function_name= f_col_char4;
+eval CREATE FUNCTION $function_name (i INT) RETURNS CHAR(26) DETERMINISTIC
+RETURN
+CONCAT('B',RPAD(CAST(i AS CHAR),20,' '), at extra_string,'E');
+eval SELECT CONCAT('->', $function_name(my_col), '<-') $part;
+
+# Auxiliary table for figuring out the impact of scenarios on
+# information_schema.innodb_metrics content.
+CREATE TABLE my_metrics LIKE information_schema.innodb_metrics;
+ALTER TABLE my_metrics ADD COLUMN phase ENUM('after', 'before'),
+DROP COLUMN SUBSYSTEM, DROP COLUMN TYPE, DROP COLUMN COMMENT,
+ADD PRIMARY KEY (NAME,phase);
+let $empty_my_metrics= DELETE FROM my_metrics;
+let $before_my_metrics= INSERT INTO my_metrics
+SELECT NAME, COUNT, MAX_COUNT, MIN_COUNT, AVG_COUNT,
+COUNT_RESET, MAX_COUNT_RESET, MIN_COUNT_RESET, AVG_COUNT_RESET,
+TIME_ENABLED, TIME_DISABLED, TIME_ELAPSED, TIME_RESET,
+STATUS, 'before'
+FROM information_schema.innodb_metrics
+WHERE NAME LIKE 'innodb_rwlock_sx_%';
+let $after_my_metrics= INSERT INTO my_metrics
+SELECT NAME, COUNT, MAX_COUNT, MIN_COUNT, AVG_COUNT,
+COUNT_RESET, MAX_COUNT_RESET, MIN_COUNT_RESET, AVG_COUNT_RESET,
+TIME_ENABLED, TIME_DISABLED, TIME_ELAPSED, TIME_RESET,
+STATUS, 'after'
+FROM information_schema.innodb_metrics
+WHERE NAME LIKE 'innodb_rwlock_sx_%';
+let $print_after_my_metrics= SELECT NAME, COUNT_RESET FROM my_metrics
+WHERE phase = 'after' ORDER BY NAME;
+
+# The main table for testing.
+CREATE TABLE t1 (
+   col_int0 BIGINT,
+   col_int1 BIGINT,
+   col_int2 BIGINT,
+   col_int3 BIGINT,
+   col_blob BLOB,
+   col_char0 VARCHAR(255),
+   col_char1 VARCHAR(30),
+   col_char2 VARCHAR(30),
+   col_char3 VARCHAR(30),
+   col_char4 VARCHAR(30)
+) ENGINE = InnoDB;
+
+# Use many indexes with mostly significant size in order to cause
+# some heavy use of sx locks during data generation.
+ALTER TABLE t1 ADD UNIQUE KEY uidx_col_int0 (col_int0),
+ADD UNIQUE KEY uidx1 (col_int1, col_char0),
+ADD UNIQUE KEY uidx2 (col_int2, col_char0, col_int1),
+ADD UNIQUE KEY uidx3 (col_int3, col_int2, col_char0),
+ADD UNIQUE KEY uidx4 (col_char1, col_char0),
+ADD UNIQUE KEY uidx5 (col_char2, col_char0, col_char1),
+ADD UNIQUE KEY uidx6 (col_char3, col_char2, col_char0),
+ADD UNIQUE KEY uidx7 (col_int1, col_int2, col_int3, col_char4,
+                 col_char1, col_char2, col_char3, col_char0),
+ADD KEY idx8 (col_blob(10), col_char4);
+
+delimiter |;
+CREATE PROCEDURE proc_fill_t1 (max_row_count INT, load_unit INT)
+BEGIN
+   DECLARE my_count INTEGER DEFAULT 0;
+   DECLARE max_load_count INTEGER DEFAULT 0;
+   DROP TABLE IF EXISTS t0;
+   CREATE TEMPORARY TABLE t0 (col_int0 BIGINT, PRIMARY KEY(col_int0));
+   WHILE (my_count < load_unit ) DO
+      SET my_count = my_count + 1;
+      INSERT INTO t0 SET col_int0 = my_count;
+   END WHILE;
+   SET max_load_count = (SELECT (max_row_count DIV load_unit) + 1 );
+   SELECT COUNT(col_int0) INTO @val FROM t1;
+   SET my_count = 0;
+   REPEAT
+      INSERT INTO t1 (col_int0, col_int1, col_int2, col_int3, col_blob,
+                      col_char0, col_char1, col_char2,col_char3,col_char4)
+      SELECT col_int0 + @val,
+             f_col_int1(col_int0 + @val),
+             f_col_int2(col_int0 + @val),
+             f_col_int3(col_int0 + @val),
+             f_col_blob(col_int0 + @val),
+             f_col_char0(col_int0 + @val),
+             f_col_char1(col_int0 + @val),
+             f_col_char2(col_int0 + @val),
+             f_col_char3(col_int0 + @val),
+             f_col_char4(col_int0 + @val)
+      FROM t0;
+      COMMIT;
+      SELECT MAX(col_int0) INTO @val FROM t1;
+      SET my_count = my_count + 1;
+   UNTIL( my_count > max_load_count OR @val >= max_row_count )
+   END REPEAT;
+   DROP TEMPORARY TABLE t0;
+END|
+delimiter ;|
+
+delimiter |;
+CREATE PROCEDURE proc_dml (max_duration INT, t1_stripe_half INT)
+BEGIN
+   DECLARE aux INTEGER DEFAULT 0;
+   DECLARE start_time INT;
+   DECLARE CONTINUE HANDLER FOR SQLEXCEPTION, SQLWARNING, NOT FOUND BEGIN END;
+
+   SET @extra_int    = CONNECTION_ID();
+   SET @extra_string = f_thread_id(@extra_int);
+   SELECT ROUND(MAX(col_int0) / 2 ) INTO @t1_half FROM t1;
+   # The user lock 'Blocker' should be already set by some other session S1.
+   # S1 starts the race by releasing that lock.
+   # Wait till the lock is released and the lock can be obtained.
+   # In order to prevent endless waiting in case of non foreseen problems
+   # limit the timespan to 30 seconds.
+   SELECT GET_LOCK('Blocker', 30) INTO @aux;
+   # Release the lock immediate so that the other "runner" sessions start too.
+   SELECT RELEASE_LOCK('Blocker') INTO @aux;
+   SET start_time = UNIX_TIMESTAMP();
+
+   WHILE (UNIX_TIMESTAMP() - start_time < max_duration) DO
+      SET @aux = @t1_half - t1_stripe_half + ROUND(RAND() * t1_stripe_half * 2);
+      UPDATE t1 SET
+         col_int1  = f_col_int1(col_int0),
+         col_int2  = f_col_int2(col_int0),
+         col_int3  = f_col_int3(col_int0),
+         col_blob  = f_col_blob(col_int0),
+         col_char0 = f_col_char0(col_int0),
+         col_char1 = f_col_char1(col_int0),
+         col_char2 = f_col_char2(col_int0),
+         col_char3 = f_col_char3(col_int0),
+         col_char4 = f_col_char4(col_int0)
+      WHERE col_int0 = @aux;
+      COMMIT;
+   END WHILE;
+END|
+delimiter ;|
+
+SET GLOBAL innodb_monitor_disable = "innodb_rwlock_sx_%";
+SET @pre_reset_ts = NOW();
+--sleep 1.1
+SET GLOBAL innodb_monitor_reset   = "innodb_rwlock_sx_%";
+SET @pre_enable_ts = NOW();
+--sleep 1.1
+SET GLOBAL innodb_monitor_enable  = "innodb_rwlock_sx_%";
+--sleep 1.1
+SET @pre_collect_ts = NOW();
+eval $empty_my_metrics;
+eval $before_my_metrics;
+--echo # TC-01 There are exact three entries "innodb_rwlock_sx_%" with the
+--echo #       with the name which follow in innodb_metrics.
+let $check_statement=
+SELECT COUNT(*) <> 3 FROM my_metrics
+WHERE NAME IN ('innodb_rwlock_sx_spin_waits',
+               'innodb_rwlock_sx_spin_rounds',
+               'innodb_rwlock_sx_os_waits');
+if(`$check_statement`)
+{
+   --echo #    fail
+   eval $check_statement;
+   SELECT NAME FROM my_metrics
+   ORDER BY NAME;
+   exit;
+}
+--echo #    pass
+
+SELECT COUNT(*) INTO @sx_count FROM my_metrics;
+
+--echo # TC-02 Counting is now enabled. ALL = @sx_count entries show that.
+let $check_statement=
+SELECT COUNT(*) <> @sx_count FROM my_metrics
+WHERE STATUS = 'enabled';
+if(`$check_statement`)
+{
+   --echo #    fail
+   eval $check_statement;
+   SELECT NAME, STATUS FROM my_metrics
+   ORDER BY NAME;
+   exit;
+}
+--echo #    pass
+
+--echo # TC-03 @pre_reset_ts < TIME_RESET. ALL = @sx_count entries show that.
+let $check_statement=
+SELECT COUNT(*) <> @sx_count FROM my_metrics
+WHERE @pre_reset_ts < TIME_RESET;
+if(`$check_statement`)
+{
+   --echo #    fail
+   eval $check_statement;
+   SELECT NAME, @pre_reset_ts, TIME_RESET FROM my_metrics
+   ORDER BY NAME;
+   exit;
+}
+--echo #    pass
+
+--echo # TC-04 @pre_enable_ts < TIME_ENABLED. ALL = @sx_count entries show that.
+let $check_statement=
+SELECT COUNT(*) <> @sx_count FROM my_metrics
+WHERE @pre_enable_ts < TIME_ENABLED;
+if(`$check_statement`)
+{
+   --echo #    fail
+   eval $check_statement;
+   SELECT NAME, @pre_enable_ts, TIME_ENABLED FROM my_metrics
+   ORDER BY NAME;
+   exit;
+}
+--echo #    pass
+
+--echo # TC-05 TIME_RESET < TIME_ENABLED AND TIME_ENABLED < @pre_collect_ts
+--echo #       AND TIME_ELAPSED > 0. ALL = @sx_count entries show that.
+let $check_statement=
+SELECT COUNT(*) <> @sx_count FROM my_metrics
+WHERE TIME_RESET < TIME_ENABLED AND TIME_ENABLED < @pre_collect_ts
+  AND TIME_ELAPSED > 0;
+if(`$check_statement`)
+{
+   --echo #    fail
+   eval $check_statement;
+   SELECT NAME, @pre_collect_ts, TIME_RESET, TIME_ENABLED, TIME_ELAPSED
+   FROM my_metrics
+   ORDER BY NAME;
+   exit;
+}
+--echo #    pass
+
+--echo # TC-06 COUNT_RESET = MAX_COUNT_RESET. ALL = @sx_count entries show that.
+let $check_statement=
+SELECT COUNT(*) <> @sx_count FROM my_metrics
+WHERE COUNT_RESET = MAX_COUNT_RESET;
+if(`$check_statement`)
+{
+   --echo #    fail
+   eval $check_statement;
+   SELECT NAME, COUNT_RESET, MAX_COUNT_RESET FROM my_metrics
+   ORDER BY NAME;
+   exit;
+}
+--echo #    pass
+
+SET GLOBAL innodb_monitor_reset = "innodb_rwlock_sx_%";
+eval $empty_my_metrics;
+eval $before_my_metrics;
+# These values (the "0") help to identify later if some record is in its
+# initial state or already modified.
+SET @extra_string = '__0_';
+SET @extra_int    =    0;
+
+--echo # TC-07 Insert some significant amount of rows into t1.
+--echo #       The system MUST survive that.
+--replace_result $max_row_count <max_row_count>
+eval SET @max_row_count = $max_row_count;
+--replace_result $load_unit <load_unit>
+eval SET @load_unit = $load_unit;
+SET @start_time = UNIX_TIMESTAMP();
+SET AUTOCOMMIT = OFF;
+eval CALL proc_fill_t1 ( @max_row_count, @load_unit);
+--echo #    pass
+SET AUTOCOMMIT = ON;
+let $t1_half= `SELECT col_int0 FROM t1
+              WHERE col_int0 >= (@val DIV 2) ORDER BY col_int0 LIMIT 1`;
+
+--disable_result_log
+if($test_debug)
+{
+   --enable_result_log
+   SELECT COUNT(*) AS table_row_count,
+          UNIX_TIMESTAMP() - @start_time AS fill_run_time
+   FROM t1;
+   eval $print_after_my_metrics;
+}
+SHOW ENGINE INNODB STATUS;
+--enable_result_log
+
+# Show that the value distribution is according to the plan.
+--vertical_results
+SELECT col_int0, col_int1, col_int2, col_int3,
+   CONCAT('->', col_blob,'<-') AS  col_blobx,
+   CONCAT('->',col_char0,'<-') AS col_char0x,
+   CONCAT('->',col_char1,'<-') AS col_char1x,
+   CONCAT('->',col_char2,'<-') AS col_char2x,
+   CONCAT('->',col_char3,'<-') AS col_char3x,
+   CONCAT('->',col_char4,'<-') AS col_char4x
+FROM t1 WHERE col_int0 between 98 AND 102;
+--horizontal_results
+
+# For experiments/interest only. Please do not remove that.
+if (0)
+{
+   ANALYZE TABLE t1;
+   SELECT n_rows, clustered_index_size, sum_of_other_index_sizes
+   FROM mysql.innodb_table_stats;
+
+   # SELECT * FROM mysql.innodb_index_stats;
+   # idx_col_int3_int0  n_diff_pfx01      1  col_int3
+   # idx_col_int3_int0  n_diff_pfx02  10000  col_int3,col_int0
+   # idx_col_int3_int0  n_diff_pfx03  10000  col_int3,col_int0,DB_ROW_ID
+   # idx_col_int3_int0  n_leaf_pages     19  Number of leaf pages in the index
+   # idx_col_int3_int0  size             20  Number of pages in the index
+
+   --vertical_results
+   SELECT t1.index_name, t1.stat_value AS idx_pages, t2.stat_value AS idx_leaf_pages,
+          (t1.stat_value - t2.stat_value - 1) / t1.stat_value AS sx_page_ratio
+   FROM mysql.innodb_index_stats t1, mysql.innodb_index_stats t2
+   WHERE t1.index_name = t2.index_name
+     AND t1.stat_name = 'size' AND t2.stat_name = 'n_leaf_pages'
+   ORDER BY t1.index_name;
+   --horizontal_results
+}
+
+eval $after_my_metrics;
+--echo # TC-8 There was a reset. COUNT_RESET = MAX_COUNT_RESET for ALL
+--echo #      = @sx_count entries before activity.
+let $check_statement=
+SELECT COUNT(*) <> @sx_count FROM my_metrics
+WHERE phase = 'before' AND COUNT_RESET = MAX_COUNT_RESET;
+if(`$check_statement`)
+{
+   --echo #    fail
+   eval $check_statement;
+   SELECT * FROM my_metrics
+   ORDER BY NAME, phase;
+   exit;
+}
+--echo #    pass
+
+--echo # TC-9 Heavy activity after reset.
+--echo #      COUNT_RESET = MAX_COUNT_RESET for ALL = @sx_count entries.
+let $check_statement=
+SELECT COUNT(*) <> @sx_count FROM my_metrics
+WHERE phase = 'after' AND COUNT_RESET = MAX_COUNT_RESET;
+if(`$check_statement`)
+{
+   --echo #    fail
+   eval $check_statement;
+   SELECT * FROM my_metrics
+   ORDER BY NAME, phase;
+   exit;
+}
+--echo #    pass
+
+--echo # TC-10 Heavy activity on sufficient big table + index structure after
+--echo #       reset. COUNT_RESET grows for ALL = @sx_count entries.
+# NAME                         | COUNT_RESET
+# -----------------------------+------------
+# innodb_rwlock_sx_os_waits    |         26
+# innodb_rwlock_sx_spin_rounds |        824
+# innodb_rwlock_sx_spin_waits  |         14
+let $check_statement=
+SELECT COUNT(*) <> @sx_count FROM my_metrics t_after JOIN my_metrics t_before
+ON t_after.COUNT_RESET > t_before.COUNT_RESET AND t_after.NAME = t_before.NAME
+WHERE t_after.phase = 'after' AND t_before.phase = 'before';
+if(`$check_statement`)
+{
+   --echo #    fail
+   eval $check_statement;
+   SELECT * FROM my_metrics
+   ORDER BY NAME, phase;
+   exit;
+}
+--echo #    pass
+
+--echo # TC-11 Let several concurrent users perform updates in t1 like mad.
+--echo #       The system MUST survive this.
+--echo #       Printing of statements is partially suppressed.
+SET GLOBAL innodb_monitor_reset = "innodb_rwlock_sx_%";
+eval $empty_my_metrics;
+eval $before_my_metrics;
+SET @start_time = UNIX_TIMESTAMP();
+eval SELECT 1 FROM t1 WHERE col_int0 = $t1_half FOR UPDATE;
+SELECT GET_LOCK('Blocker', 1000) ;
+
+--disable_query_log
+let $num= $max_con;
+while ($num)
+{
+   --connect (con$num,localhost,root,,)
+   USE my_schema;
+   # The second parameter of the procedure is size of the affected stripe / 2.
+   # A smaller stripe causes some smaller counter growth but most probably
+   # also more stress around locking in general.
+   # Example # (nnnn) = half stripe size
+   # NAME                         | COUNT_RESET (5000) | COUNT_RESET (100)
+   # -----------------------------+--------------------+----------------
+   # innodb_rwlock_sx_os_waits    |        1412        |         486
+   # innodb_rwlock_sx_spin_rounds |       44061        |       17031
+   # innodb_rwlock_sx_spin_waits  |         996        |         515
+   --send
+   eval CALL proc_dml($high_load_duration,$t1_half);
+   dec $num;
+}
+--connection default
+SELECT RELEASE_LOCK('Blocker') ;
+--sleep 3
+COMMIT;
+let $num= $max_con;
+while ($num)
+{
+   --connection con$num
+   --reap
+   dec $num;
+}
+--echo #    pass
+--connection default
+--enable_query_log
+eval $after_my_metrics;
+--disable_result_log
+if($test_debug)
+{
+   --enable_result_log
+   SELECT UNIX_TIMESTAMP() - @start_time AS update_battle_run_time;
+   eval $print_after_my_metrics;
+}
+SHOW ENGINE INNODB STATUS;
+--enable_result_log
+
+--echo # TC-12 Heavy activity on sufficient big table + index structure after
+--echo #       reset. Several concurrent sessions were running updates.
+--echo #       COUNT_RESET grows for ALL = @sx_count entries.
+# NAME                         | COUNT_RESET (5000)
+# -----------------------------+-------------------
+# innodb_rwlock_sx_os_waits    |        1412
+# innodb_rwlock_sx_spin_rounds |       44061
+# innodb_rwlock_sx_spin_waits  |         996
+let $check_statement=
+SELECT COUNT(*) <> @sx_count FROM my_metrics t_after JOIN my_metrics t_before
+ON t_after.COUNT_RESET > t_before.COUNT_RESET AND t_after.NAME = t_before.NAME
+WHERE t_after.phase = 'after' AND t_before.phase = 'before';
+if(`$check_statement`)
+{
+   --echo #    fail
+   eval $check_statement;
+   SELECT * FROM my_metrics
+   ORDER BY NAME, phase;
+   exit;
+}
+--echo #    pass
+
+--echo # TC-13 The system MUST survive a ALTER TABLE t1 ADD KEY ... on
+--echo #       the fat table t1.
+SET GLOBAL innodb_monitor_reset = "innodb_rwlock_sx_%";
+eval $empty_my_metrics;
+eval $before_my_metrics;
+SET @start_time = UNIX_TIMESTAMP();
+ALTER TABLE t1 ADD KEY idx_col_char4_col_char0 (col_char4,col_char0);
+eval $after_my_metrics;
+--echo #    pass
+--disable_result_log
+if($test_debug)
+{
+   --enable_result_log
+   SELECT UNIX_TIMESTAMP() - @start_time AS add_key_run_time;
+   eval $print_after_my_metrics;
+}
+SHOW ENGINE INNODB STATUS;
+--enable_result_log
+
+--echo # TC-14 The ADD KEY caused heavy activity on the sufficient big table.
+--echo #       COUNT_RESET grows for ALL = @sx_count entries.
+let $check_statement=
+SELECT COUNT(*) <> @sx_count FROM my_metrics t_after JOIN my_metrics t_before
+ON t_after.COUNT_RESET > t_before.COUNT_RESET AND t_after.NAME = t_before.NAME
+WHERE t_after.phase = 'after' AND t_before.phase = 'before';
+if(`$check_statement`)
+{
+   --echo #    fail
+   eval $check_statement;
+   SELECT * FROM my_metrics
+   ORDER BY NAME, phase;
+   exit;
+}
+--echo #    pass
+
+--echo # TC-15 The system MUST survive a fat update on the fat table t1.
+# Its the merge @extra_int and @extra_string into the values of most columns.
+SET GLOBAL innodb_monitor_reset = "innodb_rwlock_sx_%";
+eval $empty_my_metrics;
+eval $before_my_metrics;
+SET @start_time   = UNIX_TIMESTAMP();
+SET @extra_int    = 13;
+SET @extra_string = f_thread_id(@extra_int);
+eval UPDATE t1 SET
+   col_int1  = f_col_int1(col_int0),  col_int2  = f_col_int2(col_int0),
+   col_int3  = f_col_int3(col_int0),  col_blob  = f_col_blob(col_int0),
+   col_char0 = f_col_char0(col_int0), col_char1 = f_col_char1(col_int0),
+   col_char2 = f_col_char2(col_int0), col_char3 = f_col_char3(col_int0),
+   col_char4 = f_col_char4(col_int0)
+WHERE col_int0 BETWEEN $t1_half - 2500 AND $t1_half + 2500;
+COMMIT;
+eval $after_my_metrics;
+--disable_result_log
+if($test_debug)
+{
+   --enable_result_log
+   SELECT UNIX_TIMESTAMP() - @start_time AS total_update_run_time;
+   eval $print_after_my_metrics;
+}
+SHOW ENGINE INNODB STATUS;
+--enable_result_log
+
+--echo #    pass
+--echo # TC-16 The UPDATE caused heavy activity on the sufficient big table.
+--echo #       COUNT_RESET grows for ALL = @sx_count entries.
+let $check_statement=
+SELECT COUNT(*) <> @sx_count FROM my_metrics t_after JOIN my_metrics t_before
+ON t_after.COUNT_RESET > t_before.COUNT_RESET AND t_after.NAME = t_before.NAME
+WHERE t_after.phase = 'after' AND t_before.phase = 'before';
+if(`$check_statement`)
+{
+   --echo #    fail
+   eval $check_statement;
+   SELECT * FROM my_metrics
+   ORDER BY NAME, phase;
+   exit;
+}
+--echo #    pass
+
+# Cleanup
+let $num= $max_con;
+while ($num)
+{
+   --connection con$num
+   --disconnect con$num
+   --source include/wait_until_disconnected.inc
+   dec $num;
+}
+--connection default
+USE test;
+DROP SCHEMA my_schema;
+SET GLOBAL innodb_monitor_disable   = all;
+SET GLOBAL innodb_monitor_reset_all = all;
+--disable_warnings
+SET GLOBAL innodb_monitor_enable    = default;
+SET GLOBAL innodb_monitor_disable   = default;
+SET GLOBAL innodb_monitor_reset     = default;
+SET GLOBAL innodb_monitor_reset_all = default;
+--enable_warnings
+SET GLOBAL innodb_monitor_disable   = "innodb_rwlock_sx_%";
+SET GLOBAL innodb_monitor_reset     = "innodb_rwlock_sx_%";
+
diff --git a/storage/innobase/btr/btr0btr.cc b/storage/innobase/btr/btr0btr.cc
index fa613ef..41de4bc 100644
--- a/storage/innobase/btr/btr0btr.cc
+++ b/storage/innobase/btr/btr0btr.cc
@@ -750,8 +750,8 @@ btr_root_block_get(
 }
 
 /**************************************************************//**
-Gets the root node of a tree and x-latches it.
- at return	root page, x-latched */
+Gets the root node of a tree and sx-latches it for segment access.
+ at return root page, sx-latched */
 UNIV_INTERN
 page_t*
 btr_root_get(
@@ -759,7 +759,10 @@ btr_root_get(
 	const dict_index_t*	index,	/*!< in: index tree */
 	mtr_t*			mtr)	/*!< in: mtr */
 {
-	return(buf_block_get_frame(btr_root_block_get(index, RW_X_LATCH,
+	/* Intended to be used for segment list access.
+	SX lock doesn't block reading user data by other threads.
+	And block the segment list access by others.*/
+	return(buf_block_get_frame(btr_root_block_get(index, RW_SX_LATCH,
 						      mtr)));
 }
 
@@ -778,10 +781,11 @@ btr_height_get(
 	ulint		height;
 	buf_block_t*	root_block;
 
-	ut_ad(mtr_memo_contains(mtr, dict_index_get_lock(index),
-				MTR_MEMO_S_LOCK)
-	      || mtr_memo_contains(mtr, dict_index_get_lock(index),
-				MTR_MEMO_X_LOCK));
+	ut_ad(srv_read_only_mode
+	      || mtr_memo_contains_flagged(mtr, dict_index_get_lock(index),
+					   MTR_MEMO_S_LOCK
+					   | MTR_MEMO_X_LOCK
+					   | MTR_MEMO_SX_LOCK));
 
         /* S latches the page */
         root_block = btr_root_block_get(index, RW_S_LATCH, mtr);
@@ -1479,8 +1483,8 @@ btr_node_ptr_set_child_page_no(
 }
 
 /************************************************************//**
-Returns the child page of a node pointer and x-latches it.
- at return	child page, x-latched */
+Returns the child page of a node pointer and sx-latches it.
+ at return child page, sx-latched */
 static
 buf_block_t*
 btr_node_ptr_get_child(
@@ -1498,12 +1502,12 @@ btr_node_ptr_get_child(
 	page_no = btr_node_ptr_get_child_page_no(node_ptr, offsets);
 
 	return(btr_block_get(space, dict_table_zip_size(index->table),
-			     page_no, RW_X_LATCH, index, mtr));
+			     page_no, RW_SX_LATCH, index, mtr));
 }
 
 /************************************************************//**
 Returns the upper level node pointer to a page. It is assumed that mtr holds
-an x-latch on the tree.
+an sx-latch on the tree.
 @return	rec_get_offsets() of the node pointer record */
 static
 ulint*
@@ -1514,6 +1518,8 @@ btr_page_get_father_node_ptr_func(
 	btr_cur_t*	cursor,	/*!< in: cursor pointing to user record,
 				out: cursor on node pointer record,
 				its page x-latched */
+	ulint		latch_mode,/*!< in: BTR_CONT_MODIFY_TREE
+				or BTR_CONT_SEARCH_TREE */
 	const char*	file,	/*!< in: file name */
 	ulint		line,	/*!< in: line where called */
 	mtr_t*		mtr)	/*!< in: mtr */
@@ -1525,11 +1531,16 @@ btr_page_get_father_node_ptr_func(
 	ulint		page_no;
 	dict_index_t*	index;
 
+	ut_ad(latch_mode == BTR_CONT_MODIFY_TREE
+	      || latch_mode == BTR_CONT_SEARCH_TREE);
+
 	page_no = buf_block_get_page_no(btr_cur_get_block(cursor));
 	index = btr_cur_get_index(cursor);
 
-	ut_ad(mtr_memo_contains(mtr, dict_index_get_lock(index),
-				MTR_MEMO_X_LOCK));
+	ut_ad(srv_read_only_mode
+	      || mtr_memo_contains_flagged(mtr, dict_index_get_lock(index),
+					   MTR_MEMO_X_LOCK
+					   | MTR_MEMO_SX_LOCK));
 
 	ut_ad(dict_index_get_page(index) != page_no);
 
@@ -1540,7 +1551,7 @@ btr_page_get_father_node_ptr_func(
 	tuple = dict_index_build_node_ptr(index, user_rec, 0, heap, level);
 
 	btr_cur_search_to_nth_level(index, level + 1, tuple, PAGE_CUR_LE,
-				    BTR_CONT_MODIFY_TREE, cursor, 0,
+				    latch_mode, cursor, 0,
 				    file, line, mtr);
 
 	node_ptr = btr_cur_get_rec(cursor);
@@ -1591,7 +1602,12 @@ btr_page_get_father_node_ptr_func(
 }
 
 #define btr_page_get_father_node_ptr(of,heap,cur,mtr)			\
-	btr_page_get_father_node_ptr_func(of,heap,cur,__FILE__,__LINE__,mtr)
+	btr_page_get_father_node_ptr_func(				\
+		of,heap,cur,BTR_CONT_MODIFY_TREE,__FILE__,__LINE__,mtr)
+
+#define btr_page_get_father_node_ptr_for_validate(of,heap,cur,mtr)	\
+	btr_page_get_father_node_ptr_func(				\
+		of,heap,cur,BTR_CONT_SEARCH_TREE,__FILE__,__LINE__,mtr)
 
 /************************************************************//**
 Returns the upper level node pointer to a page. It is assumed that mtr holds
@@ -2272,8 +2288,9 @@ btr_root_raise_and_insert(
 
 	ut_a(dict_index_get_page(index) == page_get_page_no(root));
 #endif /* UNIV_BTR_DEBUG */
-	ut_ad(mtr_memo_contains(mtr, dict_index_get_lock(index),
-				MTR_MEMO_X_LOCK));
+	ut_ad(mtr_memo_contains_flagged(mtr, dict_index_get_lock(index),
+					MTR_MEMO_X_LOCK
+					| MTR_MEMO_SX_LOCK));
 	ut_ad(mtr_memo_contains(mtr, root_block, MTR_MEMO_PAGE_X_FIX));
 
 	/* Allocate a new page to the tree. Root splitting is done by first
@@ -2792,6 +2809,8 @@ btr_attach_half_pages(
 	page_zip_des_t*	upper_page_zip;
 	dtuple_t*	node_ptr_upper;
 	mem_heap_t*	heap;
+	buf_block_t*	prev_block = NULL;
+	buf_block_t*	next_block = NULL;
 
 	ut_ad(mtr_memo_contains(mtr, block, MTR_MEMO_PAGE_X_FIX));
 	ut_ad(mtr_memo_contains(mtr, new_block, MTR_MEMO_PAGE_X_FIX));
@@ -2833,6 +2852,22 @@ btr_attach_half_pages(
 		upper_page_zip = buf_block_get_page_zip(new_block);
 	}
 
+	/* Get the previous and next pages of page */
+	prev_page_no = btr_page_get_prev(page, mtr);
+	next_page_no = btr_page_get_next(page, mtr);
+	space = buf_block_get_space(block);
+	zip_size = buf_block_get_zip_size(block);
+
+	/* for consistency, both blocks should be locked, before change */
+	if (prev_page_no != FIL_NULL && direction == FSP_DOWN) {
+		prev_block = btr_block_get(space, zip_size, prev_page_no,
+					   RW_X_LATCH, index, mtr);
+	}
+	if (next_page_no != FIL_NULL && direction != FSP_DOWN) {
+		next_block = btr_block_get(space, zip_size, next_page_no,
+					   RW_X_LATCH, index, mtr);
+	}
+
 	/* Get the level of the split pages */
 	level = btr_page_get_level(buf_block_get_frame(block), mtr);
 	ut_ad(level
@@ -2853,18 +2888,9 @@ btr_attach_half_pages(
 	/* Free the memory heap */
 	mem_heap_free(heap);
 
-	/* Get the previous and next pages of page */
-
-	prev_page_no = btr_page_get_prev(page, mtr);
-	next_page_no = btr_page_get_next(page, mtr);
-	space = buf_block_get_space(block);
-	zip_size = buf_block_get_zip_size(block);
-
 	/* Update page links of the level */
 
-	if (prev_page_no != FIL_NULL) {
-		buf_block_t*	prev_block = btr_block_get(
-			space, zip_size, prev_page_no, RW_X_LATCH, index, mtr);
+	if (prev_block) {
 #ifdef UNIV_BTR_DEBUG
 		ut_a(page_is_comp(prev_block->frame) == page_is_comp(page));
 		ut_a(btr_page_get_next(prev_block->frame, mtr)
@@ -2876,9 +2902,7 @@ btr_attach_half_pages(
 				  lower_page_no, mtr);
 	}
 
-	if (next_page_no != FIL_NULL) {
-		buf_block_t*	next_block = btr_block_get(
-			space, zip_size, next_page_no, RW_X_LATCH, index, mtr);
+	if (next_block) {
 #ifdef UNIV_BTR_DEBUG
 		ut_a(page_is_comp(next_block->frame) == page_is_comp(page));
 		ut_a(btr_page_get_prev(next_block->frame, mtr)
@@ -2890,11 +2914,24 @@ btr_attach_half_pages(
 				  upper_page_no, mtr);
 	}
 
-	btr_page_set_prev(lower_page, lower_page_zip, prev_page_no, mtr);
-	btr_page_set_next(lower_page, lower_page_zip, upper_page_no, mtr);
+	if (direction == FSP_DOWN) {
+		/* lower_page is new */
+		btr_page_set_prev(lower_page, lower_page_zip,
+				  prev_page_no, mtr);
+	} else {
+		ut_ad(btr_page_get_prev(lower_page, mtr) == prev_page_no);
+	}
 
+	btr_page_set_next(lower_page, lower_page_zip, upper_page_no, mtr);
 	btr_page_set_prev(upper_page, upper_page_zip, lower_page_no, mtr);
-	btr_page_set_next(upper_page, upper_page_zip, next_page_no, mtr);
+
+	if (direction != FSP_DOWN) {
+		/* upper_page is new */
+		btr_page_set_next(upper_page, upper_page_zip,
+				  next_page_no, mtr);
+	} else {
+		ut_ad(btr_page_get_next(upper_page, mtr) == next_page_no);
+	}
 }
 
 /*************************************************************//**
@@ -2956,8 +2993,10 @@ btr_insert_into_right_sibling(
 	page_t*		page = buf_block_get_frame(block);
 	ulint		next_page_no = btr_page_get_next(page, mtr);
 
-	ut_ad(mtr_memo_contains(mtr, dict_index_get_lock(cursor->index),
-				MTR_MEMO_X_LOCK));
+	ut_ad(mtr_memo_contains_flagged(
+			mtr, dict_index_get_lock(cursor->index),
+			MTR_MEMO_X_LOCK | MTR_MEMO_SX_LOCK));
+
 	ut_ad(mtr_memo_contains(mtr, block, MTR_MEMO_PAGE_X_FIX));
 	ut_ad(heap);
 
@@ -3113,13 +3152,16 @@ btr_page_split_and_insert(
 	mem_heap_empty(*heap);
 	*offsets = NULL;
 
-	ut_ad(mtr_memo_contains(mtr, dict_index_get_lock(cursor->index),
-				MTR_MEMO_X_LOCK));
+	ut_ad(mtr_memo_contains_flagged(mtr,
+					dict_index_get_lock(cursor->index),
+					MTR_MEMO_X_LOCK
+					| MTR_MEMO_SX_LOCK));
 	ut_ad(!dict_index_is_online_ddl(cursor->index)
 	      || (flags & BTR_CREATE_FLAG)
 	      || dict_index_is_clust(cursor->index));
 #ifdef UNIV_SYNC_DEBUG
-	ut_ad(rw_lock_own(dict_index_get_lock(cursor->index), RW_LOCK_EX));
+	ut_ad(rw_lock_own_flagged(dict_index_get_lock(cursor->index),
+				  RW_LOCK_FLAG_X | RW_LOCK_FLAG_SX));
 #endif /* UNIV_SYNC_DEBUG */
 
 	block = btr_cur_get_block(cursor);
@@ -3272,7 +3314,10 @@ btr_page_split_and_insert(
 	    && !dict_index_is_online_ddl(cursor->index)) {
 
 		mtr_memo_release(mtr, dict_index_get_lock(cursor->index),
-				 MTR_MEMO_X_LOCK);
+				 MTR_MEMO_X_LOCK | MTR_MEMO_SX_LOCK);
+
+		/* NOTE: We cannot release root block latch here, because it
+		has segment header and already modified in most of cases.*/
 	}
 
 	/* 5. Move then the records to the new page */
@@ -3833,6 +3878,9 @@ btr_compress(
 	mem_heap_t*	heap;
 	ulint*		offsets;
 	ulint		nth_rec = 0; /* remove bogus warning */
+#ifdef UNIV_DEBUG
+	bool		leftmost_child;
+#endif
 	DBUG_ENTER("btr_compress");
 
 	block = btr_cur_get_block(cursor);
@@ -3841,8 +3889,9 @@ btr_compress(
 
 	btr_assert_not_corrupted(block, index);
 
-	ut_ad(mtr_memo_contains(mtr, dict_index_get_lock(index),
-				MTR_MEMO_X_LOCK));
+	ut_ad(mtr_memo_contains_flagged(mtr, dict_index_get_lock(index),
+					MTR_MEMO_X_LOCK
+					| MTR_MEMO_SX_LOCK));
 	ut_ad(mtr_memo_contains(mtr, block, MTR_MEMO_PAGE_X_FIX));
 	space = dict_index_get_space(index);
 	zip_size = dict_table_zip_size(index->table);
@@ -3877,6 +3926,13 @@ btr_compress(
 		goto func_exit;
 	}
 
+	ut_d(leftmost_child =
+		left_page_no != FIL_NULL
+		&& (page_rec_get_next(
+			page_get_infimum_rec(
+				btr_cur_get_page(&father_cursor)))
+		    == btr_cur_get_rec(&father_cursor)));
+
 	/* Decide the page to which we try to merge and which will inherit
 	the locks */
 
@@ -4071,7 +4127,11 @@ btr_compress(
 	/* Free the file page */
 	btr_page_free(index, block, mtr);
 
-	ut_ad(btr_check_node_ptr(index, merge_block, mtr));
+	/* btr_check_node_ptr() needs parent block latched.
+	If the merge_block's parent block is not same,
+	we cannot use btr_check_node_ptr() */
+	ut_ad(leftmost_child
+	      || btr_check_node_ptr(index, merge_block, mtr));
 func_exit:
 	mem_heap_free(heap);
 
@@ -4194,19 +4254,27 @@ btr_discard_page(
 	buf_block_t*	block;
 	page_t*		page;
 	rec_t*		node_ptr;
+#ifdef UNIV_DEBUG
+	btr_cur_t	parent_cursor;
+	bool		parent_is_different = false;
+#endif
 
 	block = btr_cur_get_block(cursor);
 	index = btr_cur_get_index(cursor);
 
 	ut_ad(dict_index_get_page(index) != buf_block_get_page_no(block));
-	ut_ad(mtr_memo_contains(mtr, dict_index_get_lock(index),
-				MTR_MEMO_X_LOCK));
+	ut_ad(mtr_memo_contains_flagged(mtr, dict_index_get_lock(index),
+					MTR_MEMO_X_LOCK
+					| MTR_MEMO_SX_LOCK));
 	ut_ad(mtr_memo_contains(mtr, block, MTR_MEMO_PAGE_X_FIX));
 	space = dict_index_get_space(index);
 	zip_size = dict_table_zip_size(index->table);
 
 	MONITOR_INC(MONITOR_INDEX_DISCARD);
 
+#ifdef UNIV_DEBUG
+	btr_page_get_father(index, block, mtr, &parent_cursor);
+#endif
 	/* Decide the page which will inherit the locks */
 
 	left_page_no = btr_page_get_prev(buf_block_get_frame(block), mtr);
@@ -4220,6 +4288,12 @@ btr_discard_page(
 		ut_a(btr_page_get_next(merge_page, mtr)
 		     == buf_block_get_page_no(block));
 #endif /* UNIV_BTR_DEBUG */
+		ut_d(parent_is_different =
+			(page_rec_get_next(
+				page_get_infimum_rec(
+					btr_cur_get_page(
+						&parent_cursor)))
+			 == btr_cur_get_rec(&parent_cursor)));
 	} else if (right_page_no != FIL_NULL) {
 		merge_block = btr_block_get(space, zip_size, right_page_no,
 					    RW_X_LATCH, index, mtr);
@@ -4228,6 +4302,8 @@ btr_discard_page(
 		ut_a(btr_page_get_prev(merge_page, mtr)
 		     == buf_block_get_page_no(block));
 #endif /* UNIV_BTR_DEBUG */
+		ut_d(parent_is_different = page_rec_is_supremum(
+			page_rec_get_next(btr_cur_get_rec(&parent_cursor))));
 	} else {
 		btr_discard_only_page_on_level(index, block, mtr);
 
@@ -4281,7 +4357,11 @@ btr_discard_page(
 	/* Free the file page */
 	btr_page_free(index, block, mtr);
 
-	ut_ad(btr_check_node_ptr(index, merge_block, mtr));
+	/* btr_check_node_ptr() needs parent block latched.
+	If the merge_block's parent block is not same,
+	we cannot use btr_check_node_ptr() */
+	ut_ad(parent_is_different
+	      || btr_check_node_ptr(index, merge_block, mtr));
 }
 
 #ifdef UNIV_BTR_PRINT
@@ -4344,7 +4424,7 @@ btr_print_recursive(
 	ulint		i	= 0;
 	mtr_t		mtr2;
 
-	ut_ad(mtr_memo_contains(mtr, block, MTR_MEMO_PAGE_X_FIX));
+	ut_ad(mtr_memo_contains(mtr, block, MTR_MEMO_PAGE_SX_FIX));
 	fprintf(stderr, "NODE ON LEVEL %lu page number %lu\n",
 		(ulong) btr_page_get_level(page, mtr),
 		(ulong) buf_block_get_page_no(block));
@@ -4408,7 +4488,7 @@ btr_print_index(
 
 	mtr_start(&mtr);
 
-	root = btr_root_block_get(index, RW_X_LATCH, &mtr);
+	root = btr_root_block_get(index, RW_SX_LATCH, &mtr);
 
 	btr_print_recursive(index, root, width, &heap, &offsets, &mtr);
 	if (heap) {
@@ -4417,7 +4497,7 @@ btr_print_index(
 
 	mtr_commit(&mtr);
 
-	btr_validate_index(index, 0);
+	btr_validate_index(index, 0, false);
 }
 #endif /* UNIV_BTR_PRINT */
 
@@ -4697,7 +4777,8 @@ btr_validate_level(
 /*===============*/
 	dict_index_t*	index,	/*!< in: index tree */
 	const trx_t*	trx,	/*!< in: transaction or NULL */
-	ulint		level)	/*!< in: level number */
+	ulint		level,	/*!< in: level number */
+	bool		lockout)/*!< in: true if X-latch index is intended */
 {
 	ulint		space;
 	ulint		space_flags;
@@ -4723,12 +4804,22 @@ btr_validate_level(
 #ifdef UNIV_ZIP_DEBUG
 	page_zip_des_t*	page_zip;
 #endif /* UNIV_ZIP_DEBUG */
+	ulint		savepoint = 0;
+	ulint		parent_page_no = FIL_NULL;
+	ulint		parent_right_page_no = FIL_NULL;
+	bool		rightmost_child = false;
 
 	mtr_start(&mtr);
 
-	mtr_x_lock(dict_index_get_lock(index), &mtr);
+	if (!srv_read_only_mode) {
+		if (lockout) {
+			mtr_x_lock(dict_index_get_lock(index), &mtr);
+		} else {
+			mtr_sx_lock(dict_index_get_lock(index), &mtr);
+		}
+	}
 
-	block = btr_root_block_get(index, RW_X_LATCH, &mtr);
+	block = btr_root_block_get(index, RW_SX_LATCH, &mtr);
 	page = buf_block_get_frame(block);
 	seg = page + PAGE_HEADER + PAGE_BTR_SEG_TOP;
 
@@ -4790,7 +4881,13 @@ btr_validate_level(
 loop:
 	mem_heap_empty(heap);
 	offsets = offsets2 = NULL;
-	mtr_x_lock(dict_index_get_lock(index), &mtr);
+	if (!srv_read_only_mode) {
+		if (lockout) {
+			mtr_x_lock(dict_index_get_lock(index), &mtr);
+		} else {
+			mtr_sx_lock(dict_index_get_lock(index), &mtr);
+		}
+	}
 
 #ifdef UNIV_ZIP_DEBUG
 	page_zip = buf_block_get_page_zip(block);
@@ -4839,8 +4936,9 @@ btr_validate_level(
 
 	if (right_page_no != FIL_NULL) {
 		const rec_t*	right_rec;
+		savepoint = mtr_set_savepoint(&mtr);
 		right_block = btr_block_get(space, zip_size, right_page_no,
-					    RW_X_LATCH, index, &mtr);
+					    RW_SX_LATCH, index, &mtr);
 		right_page = buf_block_get_frame(right_block);
 		if (btr_page_get_prev(right_page, &mtr)
 		    != page_get_page_no(page)) {
@@ -4909,16 +5007,25 @@ btr_validate_level(
 
 		rec_t*	node_ptr;
 
-		offsets = btr_page_get_father_block(offsets, heap, index,
-						    block, &mtr, &node_cur);
+		btr_cur_position(
+			index, page_rec_get_next(page_get_infimum_rec(page)),
+			block, &node_cur);
+		offsets = btr_page_get_father_node_ptr_for_validate(
+			offsets, heap, &node_cur, &mtr);
+
 		father_page = btr_cur_get_page(&node_cur);
 		node_ptr = btr_cur_get_rec(&node_cur);
 
+		parent_page_no = page_get_page_no(father_page);
+		parent_right_page_no = btr_page_get_next(father_page, &mtr);
+		rightmost_child = page_rec_is_supremum(
+					page_rec_get_next(node_ptr));
+
 		btr_cur_position(
 			index, page_rec_get_prev(page_get_supremum_rec(page)),
 			block, &node_cur);
-		offsets = btr_page_get_father_node_ptr(offsets, heap,
-						       &node_cur, &mtr);
+		offsets = btr_page_get_father_node_ptr_for_validate(
+				offsets, heap, &node_cur, &mtr);
 
 		if (node_ptr != btr_cur_get_rec(&node_cur)
 		    || btr_node_ptr_get_child_page_no(node_ptr, offsets)
@@ -4994,9 +5101,29 @@ btr_validate_level(
 			const rec_t*	right_node_ptr
 				= page_rec_get_next(node_ptr);
 
-			offsets = btr_page_get_father_block(
-				offsets, heap, index, right_block,
-				&mtr, &right_node_cur);
+			if (!lockout && rightmost_child) {
+				/* To obey latch order of tree blocks,
+				we should release the right_block once to
+				obtain lock of the uncle block. */
+				mtr_release_block_at_savepoint(
+					&mtr, savepoint, right_block);
+				btr_block_get(space, zip_size,
+					      parent_right_page_no,
+					      RW_SX_LATCH, index, &mtr);
+				right_block = btr_block_get(space, zip_size,
+							    right_page_no,
+							    RW_SX_LATCH, index,
+							    &mtr);
+			}
+
+			btr_cur_position(
+				index, page_rec_get_next(
+					page_get_infimum_rec(
+						buf_block_get_frame(
+							right_block))),
+				right_block, &right_node_cur);
+			offsets = btr_page_get_father_node_ptr_for_validate(
+					offsets, heap, &right_node_cur, &mtr);
 			if (right_node_ptr
 			    != page_get_supremum_rec(father_page)) {
 
@@ -5090,9 +5217,23 @@ btr_validate_level(
 
 		mtr_start(&mtr);
 
+		if (!lockout) {
+			if (rightmost_child) {
+				if (parent_right_page_no != FIL_NULL) {
+					btr_block_get(space, zip_size,
+						      parent_right_page_no,
+						      RW_SX_LATCH, index, &mtr);
+				}
+			} else if (parent_page_no != FIL_NULL) {
+				btr_block_get(space, zip_size,
+					      parent_page_no,
+					      RW_SX_LATCH, index, &mtr);
+			}
+		}
+
 		block = btr_block_get(
 			space, zip_size, right_page_no,
-			RW_X_LATCH, index, &mtr);
+			RW_SX_LATCH, index, &mtr);
 
 		page = buf_block_get_frame(block);
 
@@ -5106,13 +5247,14 @@ btr_validate_level(
 
 /**************************************************************//**
 Checks the consistency of an index tree.
- at return	TRUE if ok */
+ at return true if ok */
 UNIV_INTERN
 bool
 btr_validate_index(
 /*===============*/
 	dict_index_t*	index,	/*!< in: index */
-	const trx_t*	trx)	/*!< in: transaction or NULL */
+	const trx_t*	trx,	/*!< in: transaction or NULL */
+	bool		lockout)/*!< in: true if X-latch index is intended */
 {
 	/* Full Text index are implemented by auxiliary tables,
 	not the B-tree */
@@ -5124,7 +5266,13 @@ btr_validate_index(
 
 	mtr_start(&mtr);
 
-	mtr_x_lock(dict_index_get_lock(index), &mtr);
+	if (!srv_read_only_mode) {
+		if (lockout) {
+			mtr_x_lock(dict_index_get_lock(index), &mtr);
+		} else {
+			mtr_sx_lock(dict_index_get_lock(index), &mtr);
+		}
+	}
 
 	bool	ok = true;
 	page_t*	root = btr_root_get(index, &mtr);
@@ -5132,7 +5280,7 @@ btr_validate_index(
 
 	for (ulint i = 0; i <= n; ++i) {
 
-		if (!btr_validate_level(index, trx, n - i)) {
+		if (!btr_validate_level(index, trx, n - i, lockout)) {
 			ok = false;
 			break;
 		}
diff --git a/storage/innobase/btr/btr0cur.cc b/storage/innobase/btr/btr0cur.cc
index 1a4eb34..f71a792 100644
--- a/storage/innobase/btr/btr0cur.cc
+++ b/storage/innobase/btr/btr0cur.cc
@@ -85,6 +85,30 @@ trace information of individual record operations */
 UNIV_INTERN ibool	btr_cur_print_record_ops = FALSE;
 #endif /* UNIV_DEBUG */
 
+/** Modification types for the B-tree operation. */
+enum btr_intention_t {
+	BTR_INTENTION_DELETE,
+	BTR_INTENTION_BOTH,
+	BTR_INTENTION_INSERT
+};
+#if BTR_INTENTION_DELETE > BTR_INTENTION_BOTH
+#error "BTR_INTENTION_DELETE > BTR_INTENTION_BOTH"
+#endif
+#if BTR_INTENTION_BOTH > BTR_INTENTION_INSERT
+#error "BTR_INTENTION_BOTH > BTR_INTENTION_INSERT"
+#endif
+
+/** For the index->lock scalability improvement, only possibility of clear
+performance regression observed was caused by grown huge history list length.
+That is because the exclusive use of index->lock also worked as reserving
+free blocks and read IO bandwidth with priority. To avoid huge glowing history
+list as same level with previous implementation, prioritizes pessimistic tree
+operations by purge as the previous, when it seems to be growing huge.
+
+ Experimentally, the history list length starts to affect to performance
+throughput clearly from about 100000. */
+#define BTR_CUR_FINE_HISTORY_LENGTH	100000
+
 /** Number of searches down the B-tree in btr_cur_search_to_nth_level(). */
 UNIV_INTERN ulint	btr_cur_n_non_sea	= 0;
 /** Number of successful adaptive hash index lookups in
@@ -225,13 +249,23 @@ btr_rec_set_deleted_flag(
 #ifndef UNIV_HOTBACKUP
 /*==================== B-TREE SEARCH =========================*/
 
+#if MTR_MEMO_PAGE_S_FIX != RW_S_LATCH
+#error "MTR_MEMO_PAGE_S_FIX != RW_S_LATCH"
+#endif
+#if MTR_MEMO_PAGE_X_FIX != RW_X_LATCH
+#error "MTR_MEMO_PAGE_X_FIX != RW_X_LATCH"
+#endif
+#if MTR_MEMO_PAGE_SX_FIX != RW_SX_LATCH
+#error "MTR_MEMO_PAGE_SX_FIX != RW_SX_LATCH"
+#endif
+
 /********************************************************************//**
 Latches the leaf page or pages requested. */
 static
 void
 btr_cur_latch_leaves(
 /*=================*/
-	page_t*		page,		/*!< in: leaf page where the search
+	buf_block_t*	block,		/*!< in: leaf page where the search
 					converged */
 	ulint		space,		/*!< in: space id */
 	ulint		zip_size,	/*!< in: compressed page size in bytes
@@ -245,13 +279,15 @@ btr_cur_latch_leaves(
 	ulint		left_page_no;
 	ulint		right_page_no;
 	buf_block_t*	get_block;
+	page_t*		page = buf_block_get_frame(block);
 
-	ut_ad(page && mtr);
+	ut_ad(buf_page_in_file(&block->page));
 
 	switch (latch_mode) {
 	case BTR_SEARCH_LEAF:
 	case BTR_MODIFY_LEAF:
-		mode = latch_mode == BTR_SEARCH_LEAF ? RW_S_LATCH : RW_X_LATCH;
+	case BTR_SEARCH_TREE:
+		mode = latch_mode == BTR_MODIFY_LEAF ? RW_X_LATCH : RW_S_LATCH;
 		get_block = btr_block_get(
 			space, zip_size, page_no, mode, cursor->index, mtr);
 #ifdef UNIV_BTR_DEBUG
@@ -260,7 +296,12 @@ btr_cur_latch_leaves(
 		get_block->check_index_page_at_flush = TRUE;
 		return;
 	case BTR_MODIFY_TREE:
-		/* x-latch also brothers from left to right */
+		/* It is exclusive for other operations which calls
+		btr_page_set_prev() */
+		ut_ad(mtr_memo_contains_flagged(mtr,
+			dict_index_get_lock(cursor->index),
+			MTR_MEMO_X_LOCK | MTR_MEMO_SX_LOCK));
+		/* x-latch also siblings from left to right */
 		left_page_no = btr_page_get_prev(page, mtr);
 		mode = latch_mode;
 
@@ -305,8 +346,10 @@ btr_cur_latch_leaves(
 	case BTR_SEARCH_PREV:
 	case BTR_MODIFY_PREV:
 		mode = latch_mode == BTR_SEARCH_PREV ? RW_S_LATCH : RW_X_LATCH;
-		/* latch also left brother */
+		/* latch also left sibling */
+		rw_lock_s_lock(&block->lock);
 		left_page_no = btr_page_get_prev(page, mtr);
+		rw_lock_s_unlock(&block->lock);
 
 		if (left_page_no != FIL_NULL) {
 			get_block = btr_block_get(
@@ -334,6 +377,179 @@ btr_cur_latch_leaves(
 	ut_error;
 }
 
+/**
+Gets intention in btr_intention_t from latch_mode, and cleares the intention
+at the latch_mode.
+ at param latch_mode	in/out: pointer to latch_mode
+ at return intention for latching tree */
+static
+btr_intention_t
+btr_cur_get_and_clear_intention(
+	ulint	*latch_mode)
+{
+	btr_intention_t	intention;
+
+	switch (*latch_mode & (BTR_LATCH_FOR_INSERT | BTR_LATCH_FOR_DELETE)) {
+	case BTR_LATCH_FOR_INSERT:
+		intention = BTR_INTENTION_INSERT;
+		break;
+	case BTR_LATCH_FOR_DELETE:
+		intention = BTR_INTENTION_DELETE;
+		break;
+	default:
+		/* both or unknown */
+		intention = BTR_INTENTION_BOTH;
+	}
+	*latch_mode &= ~(BTR_LATCH_FOR_INSERT | BTR_LATCH_FOR_DELETE);
+
+	return(intention);
+}
+
+/**
+Gets the desired latch type for the root leaf (root page is root leaf)
+at the latch mode.
+ at param latch_mode	in: BTR_SEARCH_LEAF, ...
+ at return latch type */
+static
+rw_lock_type_t
+btr_cur_latch_for_root_leaf(
+	ulint	latch_mode)
+{
+	switch (latch_mode) {
+	case BTR_SEARCH_LEAF:
+	case BTR_SEARCH_TREE:
+	case BTR_SEARCH_PREV:
+		return(RW_S_LATCH);
+	case BTR_MODIFY_LEAF:
+	case BTR_MODIFY_TREE:
+	case BTR_MODIFY_PREV:
+		return(RW_X_LATCH);
+	case BTR_CONT_MODIFY_TREE:
+	case BTR_CONT_SEARCH_TREE:
+		/* A root page should be latched already,
+		and don't need to be latched here.
+		fall through (RW_NO_LATCH) */
+	case BTR_NO_LATCHES:
+		return(RW_NO_LATCH);
+	}
+
+	ut_error;
+}
+
+/**
+Detects whether the modifying record might need a modifying tree structure.
+ at param index		in: index
+ at param page		in: page
+ at param lock_intention	in: lock intention for the tree operation
+ at param rec		in: record (current node_ptr)
+ at param rec_size		in: size of the record or max size of node_ptr
+ at param zip_size		in: compressed page size in bytes
+			    or 0 for uncompressed pages
+ at param mtr		in: mtr
+ at return true if tree modification is needed */
+static
+bool
+btr_cur_will_modify_tree(
+	dict_index_t*	index,
+	const page_t*	page,
+	btr_intention_t	lock_intention,
+	const rec_t*	rec,
+	ulint		rec_size,
+	ulint		zip_size,
+	mtr_t*		mtr)
+{
+	ut_ad(!page_is_leaf(page));
+	ut_ad(mtr_memo_contains_flagged(mtr, dict_index_get_lock(index),
+					MTR_MEMO_X_LOCK
+					| MTR_MEMO_SX_LOCK));
+
+	/* Pessimistic delete of the first record causes delete & insert
+	of node_ptr at upper level. And a subsequent page shrink is
+	possible. It causes delete of node_ptr at the upper level.
+	So we should pay attention also to 2nd record not only
+	first record and last record. Because if the "delete & insert" are
+	done for the different page, the 2nd record become
+	first record and following compress might delete the record and causes
+	the uppper level node_ptr modification. */
+
+	if (lock_intention <= BTR_INTENTION_BOTH) {
+		ulint	margin;
+
+		/* check delete will cause. (BTR_INTENTION_BOTH
+		or BTR_INTENTION_DELETE) */
+		/* first, 2nd, 2nd-last and last records are 4 records */
+		if (page_get_n_recs(page) < 5) {
+			return(true);
+		}
+
+		/* is first, 2nd or last record */
+		if (page_rec_is_first(rec, page)
+		    || (mach_read_from_4(page + FIL_PAGE_NEXT) != FIL_NULL
+			&& (page_rec_is_last(rec, page)
+			    || page_rec_is_second_last(rec, page)))
+		    || (mach_read_from_4(page + FIL_PAGE_PREV) != FIL_NULL
+			&& page_rec_is_second(rec, page))) {
+			return(true);
+		}
+
+		if (lock_intention == BTR_INTENTION_BOTH) {
+			/* Delete at leftmost record in a page causes delete
+			& insert at its parent page. After that, the delete
+			might cause btr_compress() and delete record at its
+			parent page. Thus we should consider max 2 deletes. */
+
+			margin = rec_size * 2;
+		} else {
+			ut_ad(lock_intention == BTR_INTENTION_DELETE);
+
+			margin = rec_size;
+		}
+		/* NOTE: call mach_read_from_4() directly to avoid assertion
+		failure. It is safe because we already have SX latch of the
+		index tree */
+		if (page_get_data_size(page)
+			< margin + BTR_CUR_PAGE_COMPRESS_LIMIT
+		    || (mach_read_from_4(page + FIL_PAGE_NEXT)
+				== FIL_NULL
+			&& mach_read_from_4(page + FIL_PAGE_PREV)
+				== FIL_NULL)) {
+			return(true);
+		}
+	}
+
+	if (lock_intention >= BTR_INTENTION_BOTH) {
+		/* check insert will cause. BTR_INTENTION_BOTH
+		or BTR_INTENTION_INSERT)*/
+		if (page_get_max_insert_size_after_reorganize(page, 1)
+		    < BTR_CUR_PAGE_REORGANIZE_LIMIT) {
+			return(true);
+		}
+		/* needs 2 records' space for the case the single split and
+		insert cannot fit.
+		page_get_max_insert_size_after_reorganize() includes space
+		for page directory already */
+		if (page_get_max_insert_size_after_reorganize(page, 2)
+			< rec_size * 2) {
+			return(true);
+		}
+		/* TODO: optimize this condition for compressed page.
+		this is based on the worst compress rate.
+		currently looking only uncompressed page, but we can look
+		also compressed page page_zip_available() if already in the
+		buffer pool */
+		/* needs 2 records' space also for worst compress rate. */
+		if (zip_size
+		    && page_zip_empty_size(index->n_fields, zip_size)
+		       < rec_size * 2 + page_get_data_size(page)
+			 + page_dir_calc_reserved_space(
+				page_get_n_recs(page) + 2) + 1) {
+			return(true);
+		}
+	}
+
+	return(false);
+}
+
 /********************************************************************//**
 Searches an index tree and positions a tree cursor on a given level.
 NOTE: n_fields_cmp in tuple must be set so that it cannot be compared
@@ -378,7 +594,7 @@ btr_cur_search_to_nth_level(
 	ulint		line,	/*!< in: line where called */
 	mtr_t*		mtr)	/*!< in: mtr */
 {
-	page_t*		page;
+	page_t*		page = NULL; /* remove warning */
 	buf_block_t*	block;
 	ulint		space;
 	buf_block_t*	guess;
@@ -394,17 +610,36 @@ btr_cur_search_to_nth_level(
 	ulint		buf_mode;
 	ulint		estimate;
 	ulint		zip_size;
+	ulint		node_ptr_max_size = UNIV_PAGE_SIZE / 2;
 	page_cur_t*	page_cursor;
 	btr_op_t	btr_op;
 	ulint		root_height = 0; /* remove warning */
 
+	ulint		upper_rw_latch, root_leaf_rw_latch;
+	btr_intention_t	lock_intention;
+	buf_block_t*	tree_blocks[BTR_MAX_LEVELS];
+	ulint		tree_savepoints[BTR_MAX_LEVELS];
+	ulint		n_blocks = 0;
+	ulint		n_releases = 0;
+	bool		detected_same_key_root = false;
+
+	bool		retrying_for_search_prev = false;
+	ulint		leftmost_from_level = 0;
+	buf_block_t**	prev_tree_blocks = NULL;
+	ulint*		prev_tree_savepoints = NULL;
+	ulint		prev_n_blocks = 0;
+	ulint		prev_n_releases = 0;
+
 #ifdef BTR_CUR_ADAPT
 	btr_search_t*	info;
 #endif
 	mem_heap_t*	heap		= NULL;
 	ulint		offsets_[REC_OFFS_NORMAL_SIZE];
 	ulint*		offsets		= offsets_;
+	ulint		offsets2_[REC_OFFS_NORMAL_SIZE];
+	ulint*		offsets2	= offsets2_;
 	rec_offs_init(offsets_);
+	rec_offs_init(offsets2_);
 	/* Currently, PAGE_CUR_LE is the only search mode used for searches
 	ending to upper levels */
 
@@ -430,7 +665,9 @@ btr_cur_search_to_nth_level(
 
 	ut_ad(!s_latch_by_caller
 	      || mtr_memo_contains(mtr, dict_index_get_lock(index),
-				   MTR_MEMO_S_LOCK));
+				   BTR_LATCH_MODE_WITHOUT_FLAGS(latch_mode)
+				   == BTR_SEARCH_TREE
+				   ? MTR_MEMO_SX_LOCK : MTR_MEMO_S_LOCK));
 
 	/* These flags are mutually exclusive, they are lumped together
 	with the latch mode for historical reasons. It's possible for
@@ -466,11 +703,14 @@ btr_cur_search_to_nth_level(
 
 	estimate = latch_mode & BTR_ESTIMATE;
 
+	lock_intention = btr_cur_get_and_clear_intention(&latch_mode);
+
 	/* Turn the flags unrelated to the latch mode off. */
 	latch_mode = BTR_LATCH_MODE_WITHOUT_FLAGS(latch_mode);
 
 	ut_ad(!s_latch_by_caller
 	      || latch_mode == BTR_SEARCH_LEAF
+	      || latch_mode == BTR_SEARCH_TREE
 	      || latch_mode == BTR_MODIFY_LEAF);
 
 	cursor->flag = BTR_CUR_BINARY;
@@ -534,23 +774,51 @@ btr_cur_search_to_nth_level(
 
 	switch (latch_mode) {
 	case BTR_MODIFY_TREE:
-		mtr_x_lock(dict_index_get_lock(index), mtr);
+		/* Most of delete-intended operations are purging.
+		Free blocks and read IO bandwidth should be prior
+		for them, when the history list is glowing huge. */
+		if (lock_intention == BTR_INTENTION_DELETE
+		    && trx_sys->rseg_history_len > BTR_CUR_FINE_HISTORY_LENGTH
+		    && buf_get_n_pending_read_ios()) {
+			mtr_x_lock(dict_index_get_lock(index), mtr);
+		} else {
+			mtr_sx_lock(dict_index_get_lock(index), mtr);
+		}
+		upper_rw_latch = RW_X_LATCH;
 		break;
 	case BTR_CONT_MODIFY_TREE:
+	case BTR_CONT_SEARCH_TREE:
 		/* Do nothing */
-		ut_ad(mtr_memo_contains(mtr, dict_index_get_lock(index),
-					MTR_MEMO_X_LOCK));
+		ut_ad(srv_read_only_mode
+		      || mtr_memo_contains_flagged(mtr,
+						   dict_index_get_lock(index),
+						   MTR_MEMO_X_LOCK
+						   | MTR_MEMO_SX_LOCK));
+		upper_rw_latch = RW_NO_LATCH;
 		break;
 	default:
-		if (!s_latch_by_caller) {
-			mtr_s_lock(dict_index_get_lock(index), mtr);
+		if (!srv_read_only_mode) {
+			if (!s_latch_by_caller) {
+				/* BTR_SEARCH_TREE is intended to be used with
+				BTR_ALREADY_S_LATCHED */
+				ut_ad(latch_mode != BTR_SEARCH_TREE);
+
+				mtr_s_lock(dict_index_get_lock(index), mtr);
+			}
+			upper_rw_latch = RW_S_LATCH;
+		} else {
+			upper_rw_latch = RW_NO_LATCH;
 		}
 	}
+	root_leaf_rw_latch = btr_cur_latch_for_root_leaf(latch_mode);
 
 	page_cursor = btr_cur_get_page_cur(cursor);
 
 	space = dict_index_get_space(index);
 	page_no = dict_index_get_page(index);
+	if (root_leaf_rw_latch == RW_X_LATCH) {
+		node_ptr_max_size = dict_index_node_ptr_max_size(index);
+	}
 
 	up_match = 0;
 	up_bytes = 0;
@@ -589,6 +857,13 @@ btr_cur_search_to_nth_level(
 
 	if (height != 0) {
 		/* We are about to fetch the root or a non-leaf page. */
+		if ((latch_mode != BTR_MODIFY_TREE
+		     || height == level)
+		    && !retrying_for_search_prev) {
+			/* If doesn't have SX or X latch of index,
+			each pages should be latched before reading. */
+			rw_latch = upper_rw_latch;
+		}
 	} else if (latch_mode <= BTR_MODIFY_LEAF) {
 		rw_latch = latch_mode;
 
@@ -607,9 +882,12 @@ btr_cur_search_to_nth_level(
 	zip_size = dict_table_zip_size(index->table);
 
 retry_page_get:
+	ut_ad(n_blocks < BTR_MAX_LEVELS);
+	tree_savepoints[n_blocks] = mtr_set_savepoint(mtr);
 	block = buf_page_get_gen(
 		space, zip_size, page_no, rw_latch, guess, buf_mode,
 		file, line, mtr);
+	tree_blocks[n_blocks] = block;
 
 	if (block == NULL) {
 		/* This must be a search to perform an insert/delete
@@ -683,9 +961,69 @@ btr_cur_search_to_nth_level(
 		goto retry_page_get;
 	}
 
+	if (retrying_for_search_prev && height != 0) {
+		/* also latch left sibling */
+		ulint		left_page_no;
+		buf_block_t*	get_block;
+
+		ut_ad(rw_latch == RW_NO_LATCH);
+
+		rw_latch = upper_rw_latch;
+
+		rw_lock_s_lock(&block->lock);
+		left_page_no = btr_page_get_prev(page, mtr);
+		rw_lock_s_unlock(&block->lock);
+
+		if (left_page_no != FIL_NULL) {
+			ut_ad(prev_n_blocks < leftmost_from_level);
+
+			prev_tree_savepoints[prev_n_blocks]
+				= mtr_set_savepoint(mtr);
+			get_block = buf_page_get_gen(
+					space, zip_size, left_page_no,
+					rw_latch, NULL, buf_mode,
+					file, line, mtr);
+			prev_tree_blocks[prev_n_blocks] = get_block;
+			prev_n_blocks++;
+
+			/* BTR_MODIFY_TREE doesn't update prev/next_page_no,
+			without their parent page's lock. So, not needed to
+			retry here, because we have the parent page's lock. */
+		}
+
+		/* release RW_NO_LATCH page and lock with RW_S_LATCH */
+		mtr_release_block_at_savepoint(
+			mtr, tree_savepoints[n_blocks],
+			tree_blocks[n_blocks]);
+
+		tree_savepoints[n_blocks] = mtr_set_savepoint(mtr);
+		block = buf_page_get_gen(space, zip_size, page_no,
+				rw_latch, NULL, buf_mode,
+				file, line, mtr);
+		tree_blocks[n_blocks] = block;
+	}
+
 	block->check_index_page_at_flush = TRUE;
 	page = buf_block_get_frame(block);
 
+	if (height == ULINT_UNDEFINED
+	    && page_is_leaf(page)
+	    && rw_latch != RW_NO_LATCH
+	    && rw_latch != root_leaf_rw_latch) {
+		/* We should retry to get the page, because the root page
+		is latched with different level as a leaf page. */
+		ut_ad(root_leaf_rw_latch != RW_NO_LATCH);
+		ut_ad(rw_latch == RW_S_LATCH);
+
+		ut_ad(n_blocks == 0);
+		mtr_release_block_at_savepoint(
+			mtr, tree_savepoints[n_blocks],
+			tree_blocks[n_blocks]);
+
+		upper_rw_latch = root_leaf_rw_latch;
+		goto search_loop;
+	}
+
 	if (rw_latch != RW_NO_LATCH) {
 #ifdef UNIV_ZIP_DEBUG
 		const page_zip_des_t*	page_zip
@@ -719,13 +1057,14 @@ btr_cur_search_to_nth_level(
 		if (rw_latch == RW_NO_LATCH) {
 
 			btr_cur_latch_leaves(
-				page, space, zip_size, page_no, latch_mode,
+				block, space, zip_size, page_no, latch_mode,
 				cursor, mtr);
 		}
 
 		switch (latch_mode) {
 		case BTR_MODIFY_TREE:
 		case BTR_CONT_MODIFY_TREE:
+		case BTR_CONT_SEARCH_TREE:
 			break;
 		default:
 			if (!s_latch_by_caller) {
@@ -734,6 +1073,26 @@ btr_cur_search_to_nth_level(
 					mtr, savepoint,
 					dict_index_get_lock(index));
 			}
+
+			/* release upper blocks */
+			if (retrying_for_search_prev) {
+				for (;
+				     prev_n_releases < prev_n_blocks;
+				     prev_n_releases++) {
+					mtr_release_block_at_savepoint(
+						mtr,
+						prev_tree_savepoints[
+							prev_n_releases],
+						prev_tree_blocks[
+							prev_n_releases]);
+				}
+			}
+
+			for (; n_releases < n_blocks; n_releases++) {
+				mtr_release_block_at_savepoint(
+					mtr, tree_savepoints[n_releases],
+					tree_blocks[n_releases]);
+			}
 		}
 
 		page_mode = mode;
@@ -765,9 +1124,217 @@ btr_cur_search_to_nth_level(
 		offsets = rec_get_offsets(
 			node_ptr, index, offsets, ULINT_UNDEFINED, &heap);
 
+		/* If the rec is the first or last in the page for
+		pessimistic delete intention, it might cause node_ptr insert
+		for the upper level. We should change the intention and retry.
+		*/
+		if (lock_intention == BTR_INTENTION_DELETE
+		    && latch_mode == BTR_MODIFY_TREE
+		    && ((mach_read_from_4(page + FIL_PAGE_PREV) != FIL_NULL
+			 && page_rec_is_first(node_ptr, page))
+			|| (mach_read_from_4(page + FIL_PAGE_NEXT) != FIL_NULL
+			    && page_rec_is_last(node_ptr, page)))) {
+			ut_ad(upper_rw_latch == RW_X_LATCH);
+			/* release all blocks */
+			for (; n_releases <= n_blocks; n_releases++) {
+				mtr_release_block_at_savepoint(
+					mtr, tree_savepoints[n_releases],
+					tree_blocks[n_releases]);
+			}
+
+			lock_intention = BTR_INTENTION_BOTH;
+
+			page_no = dict_index_get_page(index);
+			up_match = 0;
+			low_match = 0;
+			height = ULINT_UNDEFINED;
+
+			n_blocks = 0;
+			n_releases = 0;
+
+			goto search_loop;
+		}
+
+		/* If the first or the last record of the page
+		or the same key value to the first record or last record,
+		the another page might be choosen when BTR_CONT_MODIFY_TREE.
+		So, the parent page should not released to avoiding deadlock
+		with blocking the another search with the same key value. */
+		if (!detected_same_key_root
+		    && lock_intention == BTR_INTENTION_BOTH
+		    && !dict_index_is_unique(index)
+		    && latch_mode == BTR_MODIFY_TREE
+		    && (up_match >= rec_offs_n_fields(offsets) - 1
+			|| low_match >= rec_offs_n_fields(offsets) - 1)) {
+			const rec_t*	first_rec
+						= page_rec_get_next_const(
+							page_get_infimum_rec(
+								page));
+			ulint		matched_fields;
+			ulint		matched_bytes;
+
+			ut_ad(upper_rw_latch == RW_X_LATCH);
+
+			if (node_ptr == first_rec
+			    || page_rec_is_last(node_ptr, page)) {
+				detected_same_key_root = true;
+			} else {
+				matched_fields = 0;
+				matched_bytes  = 0;
+
+				offsets2 = rec_get_offsets(
+					first_rec, index, offsets2,
+					ULINT_UNDEFINED, &heap);
+				cmp_rec_rec_with_match(node_ptr, first_rec,
+					offsets, offsets2, index, FALSE,
+					&matched_fields, &matched_bytes);
+
+				if (matched_fields
+				    >= rec_offs_n_fields(offsets) - 1) {
+					detected_same_key_root = true;
+				} else {
+					const rec_t*	last_rec;
+
+					last_rec = page_rec_get_prev_const(
+							page_get_supremum_rec(
+								page));
+
+					matched_fields = 0;
+					matched_bytes  = 0;
+
+					offsets2 = rec_get_offsets(
+						last_rec, index, offsets2,
+						ULINT_UNDEFINED, &heap);
+					cmp_rec_rec_with_match(
+						node_ptr, last_rec,
+						offsets, offsets2, index,
+						FALSE, &matched_fields, &matched_bytes);
+					if (matched_fields
+					    >= rec_offs_n_fields(offsets) - 1) {
+						detected_same_key_root = true;
+					}
+				}
+			}
+		}
+
+		/* If the page might cause modify_tree,
+		we should not release the parent page's lock. */
+		if (!detected_same_key_root
+		    && latch_mode == BTR_MODIFY_TREE
+		    && !btr_cur_will_modify_tree(
+				index, page, lock_intention, node_ptr,
+				node_ptr_max_size, zip_size, mtr)) {
+			ut_ad(upper_rw_latch == RW_X_LATCH);
+			ut_ad(n_releases <= n_blocks);
+
+			/* we can release upper blocks */
+			for (; n_releases < n_blocks; n_releases++) {
+				if (n_releases == 0) {
+					/* we should not release root page
+					to pin to same block. */
+					continue;
+				}
+
+				/* release unused blocks to unpin */
+				mtr_release_block_at_savepoint(
+					mtr, tree_savepoints[n_releases],
+					tree_blocks[n_releases]);
+			}
+		}
+
+		if (height == level
+		    && latch_mode == BTR_MODIFY_TREE) {
+			ut_ad(upper_rw_latch == RW_X_LATCH);
+			/* we should sx-latch root page, if released already.
+			It contains seg_header. */
+			if (n_releases > 0) {
+				mtr_block_sx_latch_at_savepoint(
+					mtr, tree_savepoints[0],
+					tree_blocks[0]);
+			}
+
+			/* x-latch the branch blocks not released yet. */
+			for (ulint i = n_releases; i <= n_blocks; i++) {
+				mtr_block_x_latch_at_savepoint(
+					mtr, tree_savepoints[i],
+					tree_blocks[i]);
+			}
+		}
+
+		/* We should consider prev_page of parent page, if the node_ptr
+		is the leftmost of the page. because BTR_SEARCH_PREV and
+		BTR_MODIFY_PREV latches prev_page of the leaf page. */
+		if ((latch_mode == BTR_SEARCH_PREV
+		     || latch_mode == BTR_MODIFY_PREV)
+		    && !retrying_for_search_prev) {
+			/* block should be latched for consistent
+			   btr_page_get_prev() */
+			ut_ad(mtr_memo_contains_flagged(mtr, block,
+				MTR_MEMO_PAGE_S_FIX
+				| MTR_MEMO_PAGE_X_FIX));
+
+			if (btr_page_get_prev(page, mtr) != FIL_NULL
+			    && page_rec_is_first(node_ptr, page)) {
+
+				if (leftmost_from_level == 0) {
+					leftmost_from_level = height + 1;
+				}
+			} else {
+				leftmost_from_level = 0;
+			}
+
+			if (height == 0 && leftmost_from_level > 0) {
+				/* should retry to get also prev_page
+				from level==leftmost_from_level. */
+				retrying_for_search_prev = true;
+
+				prev_tree_blocks
+					= static_cast<buf_block_t**>(
+						ut_malloc(sizeof(buf_block_t*)
+							* leftmost_from_level));
+				prev_tree_savepoints
+					= static_cast<ulint*>(
+						ut_malloc(sizeof(ulint)
+							* leftmost_from_level));
+
+				/* back to the level (leftmost_from_level+1) */
+				page_no = tree_blocks[
+					n_blocks - (leftmost_from_level - 1)]
+						->page.offset;
+
+				for (ulint i = n_blocks
+					       - (leftmost_from_level - 1);
+				     i <= n_blocks; i++) {
+					mtr_release_block_at_savepoint(
+						mtr, tree_savepoints[i],
+						tree_blocks[i]);
+				}
+
+				n_blocks -= (leftmost_from_level - 1);
+				height = leftmost_from_level;
+				ut_ad(n_releases == 0);
+
+				/* replay up_match, low_match */
+				up_match = 0;
+				low_match = 0;
+				up_bytes = 0;
+				low_bytes = 0;
+				for (ulint i = 0; i < n_blocks; i++) {
+					page_cur_search_with_match(
+						tree_blocks[i], index, tuple,
+						page_mode, &up_match, &up_bytes,
+						&low_match, &low_bytes, page_cursor);
+				}
+
+				goto search_loop;
+			}
+		}
+
 		/* Go to the child node */
 		page_no = btr_node_ptr_get_child_page_no(node_ptr, offsets);
 
+		n_blocks++;
+
 		if (UNIV_UNLIKELY(height == 0 && dict_index_is_ibuf(index))) {
 			/* We're doing a search on an ibuf tree and we're one
 			level above the leaf page. */
@@ -783,12 +1350,43 @@ btr_cur_search_to_nth_level(
 	}
 
 	if (level != 0) {
-		/* x-latch the page */
-		buf_block_t*	child_block = btr_block_get(
-			space, zip_size, page_no, RW_X_LATCH, index, mtr);
+		if (upper_rw_latch == RW_NO_LATCH) {
+			/* latch the page */
+			buf_block_t*	child_block;
+
+			if (latch_mode == BTR_CONT_MODIFY_TREE) {
+				child_block = btr_block_get(
+						space, zip_size, page_no,
+						RW_X_LATCH, index, mtr);
+			} else {
+				ut_ad(latch_mode == BTR_CONT_SEARCH_TREE);
+				child_block = btr_block_get(
+						space, zip_size, page_no,
+						RW_SX_LATCH, index, mtr);
+			}
 
-		page = buf_block_get_frame(child_block);
-		btr_assert_not_corrupted(child_block, index);
+			btr_assert_not_corrupted(child_block, index);
+		} else {
+			ut_ad(mtr_memo_contains(mtr, block, upper_rw_latch));
+			btr_assert_not_corrupted(block, index);
+
+			if (s_latch_by_caller) {
+				ut_ad(latch_mode == BTR_SEARCH_TREE);
+				/* to exclude modifying tree operations
+				should sx-latch the index. */
+				ut_ad(mtr_memo_contains(
+					mtr, dict_index_get_lock(index),
+					MTR_MEMO_SX_LOCK));
+				/* because has sx-latch of index,
+				can release upper blocks. */
+				for (; n_releases < n_blocks; n_releases++) {
+					mtr_release_block_at_savepoint(
+						mtr,
+						tree_savepoints[n_releases],
+						tree_blocks[n_releases]);
+				}
+			}
+		}
 	} else {
 		cursor->low_match = low_match;
 		cursor->low_bytes = low_bytes;
@@ -818,6 +1416,11 @@ btr_cur_search_to_nth_level(
 		mem_heap_free(heap);
 	}
 
+	if (retrying_for_search_prev) {
+		ut_free(prev_tree_blocks);
+		ut_free(prev_tree_savepoints);
+	}
+
 	if (has_search_latch) {
 
 		rw_lock_s_lock(&btr_search_latch);
@@ -845,11 +1448,18 @@ btr_cur_open_at_index_side_func(
 	ulint		page_no;
 	ulint		space;
 	ulint		zip_size;
+	ulint		node_ptr_max_size = UNIV_PAGE_SIZE / 2;
 	ulint		height;
 	ulint		root_height = 0; /* remove warning */
 	rec_t*		node_ptr;
 	ulint		estimate;
 	ulint		savepoint;
+	ulint		upper_rw_latch, root_leaf_rw_latch;
+	btr_intention_t	lock_intention;
+	buf_block_t*	tree_blocks[BTR_MAX_LEVELS];
+	ulint		tree_savepoints[BTR_MAX_LEVELS];
+	ulint		n_blocks = 0;
+	ulint		n_releases = 0;
 	mem_heap_t*	heap		= NULL;
 	ulint		offsets_[REC_OFFS_NORMAL_SIZE];
 	ulint*		offsets		= offsets_;
@@ -860,6 +1470,20 @@ btr_cur_open_at_index_side_func(
 
 	ut_ad(level != ULINT_UNDEFINED);
 
+	bool	s_latch_by_caller;
+
+	s_latch_by_caller = latch_mode & BTR_ALREADY_S_LATCHED;
+	latch_mode &= ~BTR_ALREADY_S_LATCHED;
+
+	lock_intention = btr_cur_get_and_clear_intention(&latch_mode);
+
+	/* This function doesn't need to lock left page of the leaf page */
+	if (latch_mode == BTR_SEARCH_PREV) {
+		latch_mode = BTR_SEARCH_LEAF;
+	} else if (latch_mode == BTR_MODIFY_PREV) {
+		latch_mode = BTR_MODIFY_LEAF;
+	}
+
 	/* Store the position of the tree latch we push to mtr so that we
 	know how to release it when we have latched the leaf node */
 
@@ -867,18 +1491,42 @@ btr_cur_open_at_index_side_func(
 
 	switch (latch_mode) {
 	case BTR_CONT_MODIFY_TREE:
+	case BTR_CONT_SEARCH_TREE:
+		upper_rw_latch = RW_NO_LATCH;
 		break;
 	case BTR_MODIFY_TREE:
-		mtr_x_lock(dict_index_get_lock(index), mtr);
-		break;
-	case BTR_SEARCH_LEAF | BTR_ALREADY_S_LATCHED:
-	case BTR_MODIFY_LEAF | BTR_ALREADY_S_LATCHED:
-		ut_ad(mtr_memo_contains(mtr, dict_index_get_lock(index),
-					MTR_MEMO_S_LOCK));
+		/* Most of delete-intended operations are purging.
+		Free blocks and read IO bandwidth should be prior
+		for them, when the history list is glowing huge. */
+		if (lock_intention == BTR_INTENTION_DELETE
+		    && trx_sys->rseg_history_len > BTR_CUR_FINE_HISTORY_LENGTH
+		    && buf_get_n_pending_read_ios()) {
+			mtr_x_lock(dict_index_get_lock(index), mtr);
+		} else {
+			mtr_sx_lock(dict_index_get_lock(index), mtr);
+		}
+		upper_rw_latch = RW_X_LATCH;
 		break;
 	default:
-		mtr_s_lock(dict_index_get_lock(index), mtr);
+		ut_ad(!s_latch_by_caller
+		      || mtr_memo_contains(mtr, dict_index_get_lock(index),
+					   latch_mode == BTR_SEARCH_TREE
+					   ? MTR_MEMO_SX_LOCK
+					   : MTR_MEMO_S_LOCK));
+		if (!srv_read_only_mode) {
+			if (!s_latch_by_caller) {
+				/* BTR_SEARCH_TREE is intended to be used with
+				BTR_ALREADY_S_LATCHED */
+				ut_ad(latch_mode != BTR_SEARCH_TREE);
+
+				mtr_s_lock(dict_index_get_lock(index), mtr);
+			}
+			upper_rw_latch = RW_S_LATCH;
+		} else {
+			upper_rw_latch = RW_NO_LATCH;
+		}
 	}
+	root_leaf_rw_latch = btr_cur_latch_for_root_leaf(latch_mode);
 
 	page_cursor = btr_cur_get_page_cur(cursor);
 	cursor->index = index;
@@ -886,16 +1534,53 @@ btr_cur_open_at_index_side_func(
 	space = dict_index_get_space(index);
 	zip_size = dict_table_zip_size(index->table);
 	page_no = dict_index_get_page(index);
+	if (root_leaf_rw_latch == RW_X_LATCH) {
+		node_ptr_max_size = dict_index_node_ptr_max_size(index);
+	}
 
 	height = ULINT_UNDEFINED;
 
 	for (;;) {
 		buf_block_t*	block;
 		page_t*		page;
+		ulint		rw_latch;
+
+		ut_ad(n_blocks < BTR_MAX_LEVELS);
+
+		if (height != 0
+		    && (latch_mode != BTR_MODIFY_TREE
+			|| height == level)) {
+			rw_latch = upper_rw_latch;
+		} else {
+			rw_latch = RW_NO_LATCH;
+		}
+
+		tree_savepoints[n_blocks] = mtr_set_savepoint(mtr);
 		block = buf_page_get_gen(space, zip_size, page_no,
-					 RW_NO_LATCH, NULL, BUF_GET,
+					 rw_latch, NULL, BUF_GET,
 					 file, line, mtr);
+		tree_blocks[n_blocks] = block;
+
 		page = buf_block_get_frame(block);
+
+		if (height == ULINT_UNDEFINED
+		    && btr_page_get_level(page, mtr) == 0
+		    && rw_latch != RW_NO_LATCH
+		    && rw_latch != root_leaf_rw_latch) {
+			/* We should retry to get the page, because the root page
+			is latched with different level as a leaf page. */
+			ut_ad(root_leaf_rw_latch != RW_NO_LATCH);
+			ut_ad(rw_latch == RW_S_LATCH);
+
+			ut_ad(n_blocks == 0);
+			mtr_release_block_at_savepoint(
+				mtr, tree_savepoints[n_blocks],
+				tree_blocks[n_blocks]);
+
+			upper_rw_latch = root_leaf_rw_latch;
+			continue;
+		}
+
 		ut_ad(fil_page_get_type(page) == FIL_PAGE_INDEX);
 		ut_ad(index->id == btr_page_get_index_id(page));
 
@@ -913,12 +1598,16 @@ btr_cur_open_at_index_side_func(
 		}
 
 		if (height == level) {
-			btr_cur_latch_leaves(
-				page, space, zip_size, page_no,
-				latch_mode & ~BTR_ALREADY_S_LATCHED,
-				cursor, mtr);
-
-			if (height == 0) {
+			if (srv_read_only_mode) {
+				btr_cur_latch_leaves(
+					block, space, zip_size, page_no,
+					latch_mode, cursor, mtr);
+			} else if (height == 0) {
+				if (rw_latch == RW_NO_LATCH) {
+					btr_cur_latch_leaves(
+						block, space, zip_size, page_no,
+						latch_mode, cursor, mtr);
+				}
 				/* In versions <= 3.23.52 we had
 				forgotten to release the tree latch
 				here. If in an index scan we had to
@@ -930,15 +1619,55 @@ btr_cur_open_at_index_side_func(
 				switch (latch_mode) {
 				case BTR_MODIFY_TREE:
 				case BTR_CONT_MODIFY_TREE:
-				case BTR_SEARCH_LEAF | BTR_ALREADY_S_LATCHED:
-				case BTR_MODIFY_LEAF | BTR_ALREADY_S_LATCHED:
+				case BTR_CONT_SEARCH_TREE:
 					break;
 				default:
-					/* Release the tree s-latch */
-
-					mtr_release_s_latch_at_savepoint(
-						mtr, savepoint,
-						dict_index_get_lock(index));
+					if (!s_latch_by_caller) {
+						/* Release the tree s-latch */
+						mtr_release_s_latch_at_savepoint(
+							mtr, savepoint,
+							dict_index_get_lock(
+								index));
+					}
+
+					/* release upper blocks */
+					for (; n_releases < n_blocks;
+					     n_releases++) {
+						mtr_release_block_at_savepoint(
+							mtr,
+							tree_savepoints[
+								n_releases],
+							tree_blocks[
+								n_releases]);
+					}
+				}
+			} else { /* height != 0 */
+				/* We already have the block latched. */
+				ut_ad(latch_mode == BTR_SEARCH_TREE);
+				ut_ad(s_latch_by_caller);
+				ut_ad(upper_rw_latch == RW_S_LATCH);
+
+				ut_ad(mtr_memo_contains(mtr, block,
+							upper_rw_latch));
+
+				if (s_latch_by_caller) {
+					/* to exclude modifying tree operations
+					should sx-latch the index. */
+					ut_ad(mtr_memo_contains(
+						mtr,
+						dict_index_get_lock(index),
+						MTR_MEMO_SX_LOCK));
+					/* because has sx-latch of index,
+					can release upper blocks. */
+					for (; n_releases < n_blocks;
+					     n_releases++) {
+						mtr_release_block_at_savepoint(
+							mtr,
+							tree_savepoints[
+								n_releases],
+							tree_blocks[
+								n_releases]);
+					}
 				}
 			}
 		}
@@ -975,8 +1704,81 @@ btr_cur_open_at_index_side_func(
 		node_ptr = page_cur_get_rec(page_cursor);
 		offsets = rec_get_offsets(node_ptr, cursor->index, offsets,
 					  ULINT_UNDEFINED, &heap);
+
+		/* If the rec is the first or last in the page for
+		pessimistic delete intention, it might cause node_ptr insert
+		for the upper level. We should change the intention and retry.
+		*/
+		if (lock_intention == BTR_INTENTION_DELETE
+		    && latch_mode == BTR_MODIFY_TREE
+		    && ((mach_read_from_4(page + FIL_PAGE_PREV) != FIL_NULL
+			 && page_rec_is_first(node_ptr, page))
+			|| (mach_read_from_4(page + FIL_PAGE_NEXT) != FIL_NULL
+			    && page_rec_is_last(node_ptr, page)))) {
+			ut_ad(upper_rw_latch == RW_X_LATCH);
+			/* release all blocks */
+			for (; n_releases <= n_blocks; n_releases++) {
+				mtr_release_block_at_savepoint(
+					mtr, tree_savepoints[n_releases],
+					tree_blocks[n_releases]);
+			}
+
+			lock_intention = BTR_INTENTION_BOTH;
+
+			page_no = dict_index_get_page(index);
+			height = ULINT_UNDEFINED;
+
+			n_blocks = 0;
+			n_releases = 0;
+
+			continue;
+		}
+
+		if (latch_mode == BTR_MODIFY_TREE
+		    && !btr_cur_will_modify_tree(
+				cursor->index, page, lock_intention, node_ptr,
+				node_ptr_max_size, zip_size, mtr)) {
+			ut_ad(upper_rw_latch == RW_X_LATCH);
+			ut_ad(n_releases <= n_blocks);
+
+			/* we can release upper blocks */
+			for (; n_releases < n_blocks; n_releases++) {
+				if (n_releases == 0) {
+					/* we should not release root page
+					to pin to same block. */
+					continue;
+				}
+
+				/* release unused blocks to unpin */
+				mtr_release_block_at_savepoint(
+					mtr, tree_savepoints[n_releases],
+					tree_blocks[n_releases]);
+			}
+		}
+
+		if (height == level
+		    && latch_mode == BTR_MODIFY_TREE) {
+			ut_ad(upper_rw_latch == RW_X_LATCH);
+			/* we should sx-latch root page, if released already.
+			It contains seg_header. */
+			if (n_releases > 0) {
+				mtr_block_sx_latch_at_savepoint(
+					mtr, tree_savepoints[0],
+					tree_blocks[0]);
+			}
+
+			/* x-latch the branch blocks not released yet. */
+			for (ulint i = n_releases; i <= n_blocks; i++) {
+				mtr_block_x_latch_at_savepoint(
+					mtr, tree_savepoints[i],
+					tree_blocks[i]);
+			}
+		}
+
 		/* Go to the child node */
 		page_no = btr_node_ptr_get_child_page_no(node_ptr, offsets);
+
+		n_blocks++;
 	}
 
 	if (heap) {
@@ -1001,39 +1803,112 @@ btr_cur_open_at_rnd_pos_func(
 	ulint		page_no;
 	ulint		space;
 	ulint		zip_size;
+	ulint		node_ptr_max_size = UNIV_PAGE_SIZE / 2;
 	ulint		height;
 	rec_t*		node_ptr;
+	ulint		savepoint;
+	ulint		upper_rw_latch, root_leaf_rw_latch;
+	btr_intention_t	lock_intention;
+	buf_block_t*	tree_blocks[BTR_MAX_LEVELS];
+	ulint		tree_savepoints[BTR_MAX_LEVELS];
+	ulint		n_blocks = 0;
+	ulint		n_releases = 0;
 	mem_heap_t*	heap		= NULL;
 	ulint		offsets_[REC_OFFS_NORMAL_SIZE];
 	ulint*		offsets		= offsets_;
 	rec_offs_init(offsets_);
 
+	lock_intention = btr_cur_get_and_clear_intention(&latch_mode);
+
+	savepoint = mtr_set_savepoint(mtr);
+
 	switch (latch_mode) {
 	case BTR_MODIFY_TREE:
-		mtr_x_lock(dict_index_get_lock(index), mtr);
+		/* Most of delete-intended operations are purging.
+		Free blocks and read IO bandwidth should be prior
+		for them, when the history list is glowing huge. */
+		if (lock_intention == BTR_INTENTION_DELETE
+		    && trx_sys->rseg_history_len > BTR_CUR_FINE_HISTORY_LENGTH
+		    && buf_get_n_pending_read_ios()) {
+			mtr_x_lock(dict_index_get_lock(index), mtr);
+		} else {
+			mtr_sx_lock(dict_index_get_lock(index), mtr);
+		}
+		upper_rw_latch = RW_X_LATCH;
 		break;
+	case BTR_SEARCH_PREV:
+	case BTR_MODIFY_PREV:
+		/* This function doesn't support left uncle
+		   page lock for left leaf page lock, when
+		   needed. */
+	case BTR_SEARCH_TREE:
+	case BTR_CONT_MODIFY_TREE:
+	case BTR_CONT_SEARCH_TREE:
+		ut_ad(0);
+		/* fall through */
 	default:
-		ut_ad(latch_mode != BTR_CONT_MODIFY_TREE);
-		mtr_s_lock(dict_index_get_lock(index), mtr);
+		if (!srv_read_only_mode) {
+			mtr_s_lock(dict_index_get_lock(index), mtr);
+			upper_rw_latch = RW_S_LATCH;
+		} else {
+			upper_rw_latch = RW_NO_LATCH;
+		}
 	}
 
+	root_leaf_rw_latch = btr_cur_latch_for_root_leaf(latch_mode);
+
 	page_cursor = btr_cur_get_page_cur(cursor);
 	cursor->index = index;
 
 	space = dict_index_get_space(index);
 	zip_size = dict_table_zip_size(index->table);
 	page_no = dict_index_get_page(index);
+	if (root_leaf_rw_latch == RW_X_LATCH) {
+		node_ptr_max_size = dict_index_node_ptr_max_size(index);
+	}
 
 	height = ULINT_UNDEFINED;
 
 	for (;;) {
 		buf_block_t*	block;
 		page_t*		page;
+		ulint		rw_latch;
+
+		ut_ad(n_blocks < BTR_MAX_LEVELS);
+
+		if (height != 0
+		    && latch_mode != BTR_MODIFY_TREE) {
+			rw_latch = upper_rw_latch;
+		} else {
+			rw_latch = RW_NO_LATCH;
+		}
 
+		tree_savepoints[n_blocks] = mtr_set_savepoint(mtr);
 		block = buf_page_get_gen(space, zip_size, page_no,
-					 RW_NO_LATCH, NULL, BUF_GET,
+					 rw_latch, NULL, BUF_GET,
 					 file, line, mtr);
+		tree_blocks[n_blocks] = block;
+
 		page = buf_block_get_frame(block);
+
+		if (height == ULINT_UNDEFINED
+		    && btr_page_get_level(page, mtr) == 0
+		    && rw_latch != RW_NO_LATCH
+		    && rw_latch != root_leaf_rw_latch) {
+			/* We should retry to get the page, because the root page
+			is latched with different level as a leaf page. */
+			ut_ad(root_leaf_rw_latch != RW_NO_LATCH);
+			ut_ad(rw_latch == RW_S_LATCH);
+
+			ut_ad(n_blocks == 0);
+			mtr_release_block_at_savepoint(
+				mtr, tree_savepoints[n_blocks],
+				tree_blocks[n_blocks]);
+
+			upper_rw_latch = root_leaf_rw_latch;
+			continue;
+		}
+
 		ut_ad(fil_page_get_type(page) == FIL_PAGE_INDEX);
 		ut_ad(index->id == btr_page_get_index_id(page));
 
@@ -1044,8 +1919,37 @@ btr_cur_open_at_rnd_pos_func(
 		}
 
 		if (height == 0) {
-			btr_cur_latch_leaves(page, space, zip_size, page_no,
-					     latch_mode, cursor, mtr);
+			if (rw_latch == RW_NO_LATCH
+			    || srv_read_only_mode) {
+				btr_cur_latch_leaves(
+					block, space, zip_size, page_no,
+					latch_mode, cursor, mtr);
+			}
+
+			/* btr_cur_open_at_index_side_func() and
+			btr_cur_search_to_nth_level() release
+			tree s-latch here.*/
+			switch (latch_mode) {
+			case BTR_MODIFY_TREE:
+			case BTR_CONT_MODIFY_TREE:
+			case BTR_CONT_SEARCH_TREE:
+				break;
+			default:
+				/* Release the tree s-latch */
+				if (!srv_read_only_mode) {
+					mtr_release_s_latch_at_savepoint(
+						mtr, savepoint,
+						dict_index_get_lock(index));
+				}
+
+				/* release upper blocks */
+				for (; n_releases < n_blocks; n_releases++) {
+					mtr_release_block_at_savepoint(
+						mtr,
+						tree_savepoints[n_releases],
+						tree_blocks[n_releases]);
+				}
+			}
 		}
 
 		page_cur_open_on_rnd_user_rec(block, page_cursor);
@@ -1062,8 +1966,81 @@ btr_cur_open_at_rnd_pos_func(
 		node_ptr = page_cur_get_rec(page_cursor);
 		offsets = rec_get_offsets(node_ptr, cursor->index, offsets,
 					  ULINT_UNDEFINED, &heap);
+
+		/* If the rec is the first or last in the page for
+		pessimistic delete intention, it might cause node_ptr insert
+		for the upper level. We should change the intention and retry.
+		*/
+		if (lock_intention == BTR_INTENTION_DELETE
+		    && latch_mode == BTR_MODIFY_TREE
+		    && ((mach_read_from_4(page + FIL_PAGE_PREV) != FIL_NULL
+			 && page_rec_is_first(node_ptr, page))
+			|| (mach_read_from_4(page + FIL_PAGE_NEXT) != FIL_NULL
+			    && page_rec_is_last(node_ptr, page)))) {
+			ut_ad(upper_rw_latch == RW_X_LATCH);
+			/* release all blocks */
+			for (; n_releases <= n_blocks; n_releases++) {
+				mtr_release_block_at_savepoint(
+					mtr, tree_savepoints[n_releases],
+					tree_blocks[n_releases]);
+			}
+
+			lock_intention = BTR_INTENTION_BOTH;
+
+			page_no = dict_index_get_page(index);
+			height = ULINT_UNDEFINED;
+
+			n_blocks = 0;
+			n_releases = 0;
+
+			continue;
+		}
+
+		if (latch_mode == BTR_MODIFY_TREE
+		    && !btr_cur_will_modify_tree(
+				cursor->index, page, lock_intention, node_ptr,
+				node_ptr_max_size, zip_size, mtr)) {
+			ut_ad(upper_rw_latch == RW_X_LATCH);
+			ut_ad(n_releases <= n_blocks);
+
+			/* we can release upper blocks */
+			for (; n_releases < n_blocks; n_releases++) {
+				if (n_releases == 0) {
+					/* we should not release root page
+					to pin to same block. */
+					continue;
+				}
+
+				/* release unused blocks to unpin */
+				mtr_release_block_at_savepoint(
+					mtr, tree_savepoints[n_releases],
+					tree_blocks[n_releases]);
+			}
+		}
+
+		if (height == 0
+		    && latch_mode == BTR_MODIFY_TREE) {
+			ut_ad(upper_rw_latch == RW_X_LATCH);
+			/* we should sx-latch root page, if released already.
+			It contains seg_header. */
+			if (n_releases > 0) {
+				mtr_block_sx_latch_at_savepoint(
+					mtr, tree_savepoints[0],
+					tree_blocks[0]);
+			}
+
+			/* x-latch the branch blocks not released yet. */
+			for (ulint i = n_releases; i <= n_blocks; i++) {
+				mtr_block_x_latch_at_savepoint(
+					mtr, tree_savepoints[i],
+					tree_blocks[i]);
+			}
+		}
+
 		/* Go to the child node */
 		page_no = btr_node_ptr_get_child_page_no(node_ptr, offsets);
+
+		n_blocks++;
 	}
 
 	if (UNIV_LIKELY_NULL(heap)) {
@@ -1533,9 +2510,9 @@ btr_cur_pessimistic_insert(
 
 	*big_rec = NULL;
 
-	ut_ad(mtr_memo_contains(mtr,
-				dict_index_get_lock(btr_cur_get_index(cursor)),
-				MTR_MEMO_X_LOCK));
+	ut_ad(mtr_memo_contains_flagged(
+		mtr, dict_index_get_lock(btr_cur_get_index(cursor)),
+		MTR_MEMO_X_LOCK | MTR_MEMO_SX_LOCK));
 	ut_ad(mtr_memo_contains(mtr, btr_cur_get_block(cursor),
 				MTR_MEMO_PAGE_X_FIX));
 	ut_ad(!dict_index_is_online_ddl(index)
@@ -2458,8 +3435,9 @@ btr_cur_pessimistic_update(
 	page_zip = buf_block_get_page_zip(block);
 	index = cursor->index;
 
-	ut_ad(mtr_memo_contains(mtr, dict_index_get_lock(index),
-				MTR_MEMO_X_LOCK));
+	ut_ad(mtr_memo_contains_flagged(mtr, dict_index_get_lock(index),
+					MTR_MEMO_X_LOCK |
+					MTR_MEMO_SX_LOCK));
 	ut_ad(mtr_memo_contains(mtr, block, MTR_MEMO_PAGE_X_FIX));
 #ifdef UNIV_ZIP_DEBUG
 	ut_a(!page_zip || page_zip_validate(page_zip, page, index));
@@ -2681,6 +3659,18 @@ btr_cur_pessimistic_update(
 			ibuf_update_free_bits_zip(block, mtr);
 		}
 
+		if (!srv_read_only_mode
+		    && !big_rec_vec
+		    && page_is_leaf(page)
+		    && !dict_index_is_online_ddl(index)) {
+
+			mtr_memo_release(mtr, dict_index_get_lock(index),
+					 MTR_MEMO_X_LOCK | MTR_MEMO_SX_LOCK);
+
+			/* NOTE: We cannot release root block latch here, because it
+			has segment header and already modified in most of cases.*/
+		}
+
 		err = DB_SUCCESS;
 		goto return_after_reservations;
 	} else {
@@ -2706,12 +3696,12 @@ btr_cur_pessimistic_update(
 
 		/* btr_page_split_and_insert() in
 		btr_cur_pessimistic_insert() invokes
-		mtr_memo_release(mtr, index->lock, MTR_MEMO_X_LOCK).
+		mtr_memo_release(mtr, index->lock, MTR_MEMO_SX_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);
+		mtr_sx_lock(dict_index_get_lock(index), mtr);
 	}
 
 	/* Was the record to be updated positioned as the first user
@@ -3166,9 +4156,9 @@ btr_cur_compress_if_useful(
 				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)),
-				MTR_MEMO_X_LOCK));
+	ut_ad(mtr_memo_contains_flagged(
+		mtr, dict_index_get_lock(btr_cur_get_index(cursor)),
+		MTR_MEMO_X_LOCK | MTR_MEMO_SX_LOCK));
 	ut_ad(mtr_memo_contains(mtr, btr_cur_get_block(cursor),
 				MTR_MEMO_PAGE_X_FIX));
 
@@ -3315,6 +4305,9 @@ btr_cur_pessimistic_delete(
 	ulint		level;
 	mem_heap_t*	heap;
 	ulint*		offsets;
+#ifdef UNIV_DEBUG
+	bool		parent_latched	= false;
+#endif
 
 	block = btr_cur_get_block(cursor);
 	page = buf_block_get_frame(block);
@@ -3324,8 +4317,9 @@ btr_cur_pessimistic_delete(
 	ut_ad(!dict_index_is_online_ddl(index)
 	      || dict_index_is_clust(index)
 	      || (flags & BTR_CREATE_FLAG));
-	ut_ad(mtr_memo_contains(mtr, dict_index_get_lock(index),
-				MTR_MEMO_X_LOCK));
+	ut_ad(mtr_memo_contains_flagged(mtr, dict_index_get_lock(index),
+					MTR_MEMO_X_LOCK
+					| MTR_MEMO_SX_LOCK));
 	ut_ad(mtr_memo_contains(mtr, block, MTR_MEMO_PAGE_X_FIX));
 	if (!has_reserved_extents) {
 		/* First reserve enough free space for the file segments
@@ -3403,7 +4397,7 @@ btr_cur_pessimistic_delete(
 			btr_set_min_rec_mark(next_rec, mtr);
 		} else {
 			/* Otherwise, if we delete the leftmost node pointer
-			on a page, we have to change the father node pointer
+			on a page, we have to change the parent node pointer
 			so that it is equal to the new leftmost node pointer
 			on the page */
 
@@ -3415,6 +4409,8 @@ btr_cur_pessimistic_delete(
 
 			btr_insert_on_non_leaf_level(
 				flags, index, level + 1, node_ptr, mtr);
+
+			ut_d(parent_latched = true);
 		}
 	}
 
@@ -3425,7 +4421,8 @@ btr_cur_pessimistic_delete(
 	ut_a(!page_zip || page_zip_validate(page_zip, page, index));
 #endif /* UNIV_ZIP_DEBUG */
 
-	ut_ad(btr_check_node_ptr(index, block, mtr));
+	/* btr_check_node_ptr() needs parent block latched */
+	ut_ad(!parent_latched || btr_check_node_ptr(index, block, mtr));
 
 return_after_reservations:
 	*err = DB_SUCCESS;
@@ -3436,6 +4433,17 @@ btr_cur_pessimistic_delete(
 		ret = btr_cur_compress_if_useful(cursor, FALSE, mtr);
 	}
 
+	if (!srv_read_only_mode
+	    && page_is_leaf(page)
+	    && !dict_index_is_online_ddl(index)) {
+
+		mtr_memo_release(mtr, dict_index_get_lock(index),
+				 MTR_MEMO_X_LOCK | MTR_MEMO_SX_LOCK);
+
+		/* NOTE: We cannot release root block latch here, because it
+		has segment header and already modified in most of cases.*/
+	}
+
 	if (n_reserved > 0) {
 		fil_space_release_free_extents(index->space, n_reserved);
 	}
@@ -4010,7 +5018,6 @@ btr_estimate_number_of_different_key_vals(
 			}
 
 			matched_fields = 0;
-			matched_bytes = 0;
 			offsets_next_rec = rec_get_offsets(next_rec, index,
 							   offsets_next_rec,
 							   ULINT_UNDEFINED,
@@ -4019,8 +5026,7 @@ btr_estimate_number_of_different_key_vals(
 			cmp_rec_rec_with_match(rec, next_rec,
 					       offsets_rec, offsets_next_rec,
 					       index, stats_null_not_equal,
-					       &matched_fields,
-					       &matched_bytes);
+				               &matched_fields, &matched_bytes);
 
 			for (j = matched_fields; j < n_cols; j++) {
 				/* We add one if this index record has
@@ -4498,8 +5504,9 @@ btr_store_big_rec_extern_fields(
 	ut_ad(rec_offs_validate(rec, index, offsets));
 	ut_ad(rec_offs_any_extern(offsets));
 	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_flagged(btr_mtr, dict_index_get_lock(index),
+					MTR_MEMO_X_LOCK
+					| MTR_MEMO_SX_LOCK));
 	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));
@@ -5042,8 +6049,9 @@ btr_free_externally_stored_field(
 	mtr_t		mtr;
 
 	ut_ad(dict_index_is_clust(index));
-	ut_ad(mtr_memo_contains(local_mtr, dict_index_get_lock(index),
-				MTR_MEMO_X_LOCK));
+	ut_ad(mtr_memo_contains_flagged(local_mtr, dict_index_get_lock(index),
+					MTR_MEMO_X_LOCK
+					| MTR_MEMO_SX_LOCK));
 	ut_ad(mtr_memo_contains_page(local_mtr, field_ref,
 				     MTR_MEMO_PAGE_X_FIX));
 	ut_ad(!rec || rec_offs_validate(rec, index, offsets));
diff --git a/storage/innobase/btr/btr0pcur.cc b/storage/innobase/btr/btr0pcur.cc
index 01d2e1b..476e3fb 100644
--- a/storage/innobase/btr/btr0pcur.cc
+++ b/storage/innobase/btr/btr0pcur.cc
@@ -253,7 +253,8 @@ btr_pcur_restore_position_func(
 			index, latch_mode,
 			btr_pcur_get_btr_cur(cursor), 0, mtr);
 
-		cursor->latch_mode = latch_mode;
+		cursor->latch_mode =
+			BTR_LATCH_MODE_WITHOUT_INTENTION(latch_mode);
 		cursor->pos_state = BTR_PCUR_IS_POSITIONED;
 		cursor->block_when_stored = btr_pcur_get_block(cursor);
 
@@ -408,6 +409,7 @@ btr_pcur_move_to_next_page(
 	page_t*		page;
 	buf_block_t*	next_block;
 	page_t*		next_page;
+	ulint		mode;
 
 	ut_ad(cursor->pos_state == BTR_PCUR_IS_POSITIONED);
 	ut_ad(cursor->latch_mode != BTR_NO_LATCHES);
@@ -422,8 +424,15 @@ btr_pcur_move_to_next_page(
 
 	ut_ad(next_page_no != FIL_NULL);
 
-	next_block = btr_block_get(space, zip_size, next_page_no,
-				   cursor->latch_mode,
+	mode = cursor->latch_mode;
+	switch (mode) {
+	case BTR_SEARCH_TREE:
+		mode = BTR_SEARCH_LEAF;
+		break;
+	case BTR_MODIFY_TREE:
+		mode = BTR_MODIFY_LEAF;
+	}
+	next_block = btr_block_get(space, zip_size, next_page_no, mode,
 				   btr_pcur_get_btr_cur(cursor)->index, mtr);
 	next_page = buf_block_get_frame(next_block);
 #ifdef UNIV_BTR_DEBUG
@@ -434,7 +443,7 @@ btr_pcur_move_to_next_page(
 	next_block->check_index_page_at_flush = TRUE;
 
 	btr_leaf_page_release(btr_pcur_get_block(cursor),
-			      cursor->latch_mode, mtr);
+			      mode, mtr);
 
 	page_cur_set_before_first(next_block, btr_pcur_get_page_cur(cursor));
 
diff --git a/storage/innobase/buf/buf0buf.cc b/storage/innobase/buf/buf0buf.cc
index 0fe7fae..a431e35 100644
--- a/storage/innobase/buf/buf0buf.cc
+++ b/storage/innobase/buf/buf0buf.cc
@@ -2639,6 +2639,7 @@ buf_page_get_gen(
 	ut_ad(mtr->state == MTR_ACTIVE);
 	ut_ad((rw_latch == RW_S_LATCH)
 	      || (rw_latch == RW_X_LATCH)
+	      || (rw_latch == RW_SX_LATCH)
 	      || (rw_latch == RW_NO_LATCH));
 #ifdef UNIV_DEBUG
 	switch (mode) {
@@ -3135,6 +3136,12 @@ buf_page_get_gen(
 		fix_type = MTR_MEMO_PAGE_S_FIX;
 		break;
 
+	case RW_SX_LATCH:
+		rw_lock_sx_lock_inline(&block->lock, 0, file, line);
+
+		fix_type = MTR_MEMO_PAGE_SX_FIX;
+		break;
+
 	default:
 		ut_ad(rw_latch == RW_X_LATCH);
 		rw_lock_x_lock_inline(&fix_block->lock, 0, file, line);
@@ -3213,14 +3220,19 @@ buf_page_optimistic_get(
 			   buf_block_get_zip_size(block),
 			   buf_block_get_page_no(block), NULL));
 
-	if (rw_latch == RW_S_LATCH) {
+	switch (rw_latch) {
+	case RW_S_LATCH:
 		success = rw_lock_s_lock_nowait(&(block->lock),
 						file, line);
 		fix_type = MTR_MEMO_PAGE_S_FIX;
-	} else {
+		break;
+	case RW_X_LATCH:
 		success = rw_lock_x_lock_func_nowait_inline(&(block->lock),
 							    file, line);
 		fix_type = MTR_MEMO_PAGE_X_FIX;
+		break;
+	default:
+		ut_error; /* RW_SX_LATCH is not implemented yet */
 	}
 
 	if (UNIV_UNLIKELY(!success)) {
@@ -3332,14 +3344,19 @@ buf_page_get_known_nowait(
 
 	ut_ad(!ibuf_inside(mtr) || mode == BUF_KEEP_OLD);
 
-	if (rw_latch == RW_S_LATCH) {
+	switch (rw_latch) {
+	case RW_S_LATCH:
 		success = rw_lock_s_lock_nowait(&(block->lock),
 						file, line);
 		fix_type = MTR_MEMO_PAGE_S_FIX;
-	} else {
+		break;
+	case RW_X_LATCH:
 		success = rw_lock_x_lock_func_nowait_inline(&(block->lock),
 							    file, line);
 		fix_type = MTR_MEMO_PAGE_X_FIX;
+		break;
+	default:
+		ut_error; /* RW_SX_LATCH is not implemented yet */
 	}
 
 	if (!success) {
@@ -4414,8 +4431,8 @@ buf_page_io_complete(
 		buf_flush_write_complete(bpage);
 
 		if (uncompressed) {
-			rw_lock_s_unlock_gen(&((buf_block_t*) bpage)->lock,
-					     BUF_IO_WRITE);
+			rw_lock_sx_unlock_gen(&((buf_block_t*) bpage)->lock,
+					      BUF_IO_WRITE);
 		}
 
 		buf_pool->stat.n_pages_written++;
diff --git a/storage/innobase/buf/buf0flu.cc b/storage/innobase/buf/buf0flu.cc
index 9bd7a7c..f0c00d7 100644
--- a/storage/innobase/buf/buf0flu.cc
+++ b/storage/innobase/buf/buf0flu.cc
@@ -1013,17 +1013,16 @@ buf_flush_page(
 		rw_lock = NULL;
 
 	} else if (!(no_fix_count || flush_type == BUF_FLUSH_LIST)) {
-		/* This is a heuristic, to avoid expensive S attempts. */
+		/* This is a heuristic, to avoid expensive SX attempts. */
 		flush = FALSE;
 	} else {
 
 		rw_lock = &reinterpret_cast<buf_block_t*>(bpage)->lock;
 
 		if (flush_type != BUF_FLUSH_LIST) {
-			flush = rw_lock_s_lock_gen_nowait(
-				rw_lock, BUF_IO_WRITE);
+			flush = rw_lock_sx_lock_nowait(rw_lock, BUF_IO_WRITE);
 		} else {
-			/* Will S lock later */
+			/* Will SX lock later */
 			flush = TRUE;
 		}
 	}
@@ -1033,7 +1032,6 @@ buf_flush_page(
 		/* We are committed to flushing by the time we get here */
 
 		buf_page_set_io_fix(bpage, BUF_IO_WRITE);
-
 		buf_page_set_flush_type(bpage, flush_type);
 
 		if (buf_pool->n_flush[flush_type] == 0) {
@@ -1048,13 +1046,13 @@ buf_flush_page(
 
 		if (flush_type == BUF_FLUSH_LIST
 		    && is_uncompressed
-		    && !rw_lock_s_lock_gen_nowait(rw_lock, BUF_IO_WRITE)) {
+		    && !rw_lock_sx_lock_nowait(rw_lock, BUF_IO_WRITE)) {
 			/* avoiding deadlock possibility involves doublewrite
 			buffer, should flush it, because it might hold the
 			another block->lock. */
 			buf_dblwr_flush_buffered_writes();
 
-			rw_lock_s_lock_gen(rw_lock, BUF_IO_WRITE);
+			rw_lock_sx_lock_gen(rw_lock, BUF_IO_WRITE);
                 }
 
 		/* Even though bpage is not protected by any mutex at this
diff --git a/storage/innobase/data/data0data.cc b/storage/innobase/data/data0data.cc
index 179de79..2f50736 100644
--- a/storage/innobase/data/data0data.cc
+++ b/storage/innobase/data/data0data.cc
@@ -623,7 +623,7 @@ dtuple_convert_big_rec(
 			    || dfield_is_ext(dfield)
 			    || dfield_get_len(dfield) <= local_len
 			    || dfield_get_len(dfield)
-			    <= BTR_EXTERN_FIELD_REF_SIZE * 2) {
+			    <= BTR_EXTERN_LOCAL_STORED_MAX_SIZE) {
 				goto skip_field;
 			}
 
diff --git a/storage/innobase/dict/dict0dict.cc b/storage/innobase/dict/dict0dict.cc
index c030886..e51b430 100644
--- a/storage/innobase/dict/dict0dict.cc
+++ b/storage/innobase/dict/dict0dict.cc
@@ -2153,7 +2153,7 @@ dict_index_too_big_for_undo(
 		if (fixed_size) {
 			/* Fixed-size columns are stored locally. */
 			max_size = fixed_size;
-		} else if (max_size <= BTR_EXTERN_FIELD_REF_SIZE * 2) {
+		} else if (max_size <= BTR_EXTERN_LOCAL_STORED_MAX_SIZE) {
 			/* Short columns are stored locally. */
 		} else if (!col->ord_part
 			   || (col->max_prefix
@@ -2217,6 +2217,94 @@ dict_index_too_big_for_undo(
 #endif
 
 /****************************************************************//**
+Return maximum size of the node pointer record.
+ at return maximum size of the record in bytes */
+
+ulint
+dict_index_node_ptr_max_size(
+/*=========================*/
+	const dict_index_t*	index)	/*!< in: index */
+{
+	ulint	comp;
+	ulint	i;
+	/* maximum possible storage size of a record */
+	ulint	rec_max_size;
+
+	if (dict_index_is_univ(index)) {
+		/* cannot estimate accurately */
+		/* This is universal index for change buffer.
+		The max size of the entry is about max key length * 2.
+		(index key + primary key to be inserted to the index)
+		(The max key length is UNIV_PAGE_SIZE / 16 * 3 at
+		 ha_innobase::max_supported_key_length(),
+		 considering MAX_KEY_LENGTH = 3072 at MySQL imposes
+		 the 3500 historical InnoDB value for 16K page size case.)
+		For the universal index, node_ptr contains most of the entry.
+		And 512 is enough to contain ibuf columns and meta-data */
+		return(UNIV_PAGE_SIZE / 8 * 3 + 512);
+	}
+
+	comp = dict_table_is_comp(index->table);
+
+	/* Each record has page_no, length of page_no and header. */
+	rec_max_size = comp
+		? REC_NODE_PTR_SIZE + 1 + REC_N_NEW_EXTRA_BYTES
+		: REC_NODE_PTR_SIZE + 2 + REC_N_OLD_EXTRA_BYTES;
+
+	if (comp) {
+		/* Include the "null" flags in the
+		maximum possible record size. */
+		rec_max_size += UT_BITS_IN_BYTES(index->n_nullable);
+	} else {
+		/* For each column, include a 2-byte offset and a
+		"null" flag. */
+		rec_max_size += 2 * index->n_fields;
+	}
+
+	/* Compute the maximum possible record size. */
+	for (i = 0; i < dict_index_get_n_unique_in_tree(index); i++) {
+		const dict_field_t*	field
+			= dict_index_get_nth_field(index, i);
+		const dict_col_t*	col
+			= dict_field_get_col(field);
+		ulint			field_max_size;
+		ulint			field_ext_max_size;
+
+		/* Determine the maximum length of the index field. */
+
+		field_max_size = dict_col_get_fixed_size(col, comp);
+		if (field_max_size) {
+			/* dict_index_add_col() should guarantee this */
+			ut_ad(!field->prefix_len
+			      || field->fixed_len == field->prefix_len);
+			/* Fixed lengths are not encoded
+			in ROW_FORMAT=COMPACT. */
+			rec_max_size += field_max_size;
+			continue;
+		}
+
+		field_max_size = dict_col_get_max_size(col);
+		field_ext_max_size = field_max_size < 256 ? 1 : 2;
+
+		if (field->prefix_len
+		    && field->prefix_len < field_max_size) {
+			field_max_size = field->prefix_len;
+		}
+
+		if (comp) {
+			/* Add the extra size for ROW_FORMAT=COMPACT.
+			For ROW_FORMAT=REDUNDANT, these bytes were
+			added to rec_max_size before this loop. */
+			rec_max_size += field_ext_max_size;
+		}
+
+		rec_max_size += field_max_size;
+	}
+
+	return(rec_max_size);
+}
+
+/****************************************************************//**
 If a record of this index might not fit on a single B-tree page,
 return TRUE.
 @return	TRUE if the index record could become too big */
@@ -2305,7 +2393,7 @@ dict_index_too_big_for_tree(
 		ulint			field_ext_max_size;
 
 		/* In dtuple_convert_big_rec(), variable-length columns
-		that are longer than BTR_EXTERN_FIELD_REF_SIZE * 2
+		that are longer than BTR_EXTERN_LOCAL_STORED_MAX_SIZE
 		may be chosen for external storage.
 
 		Fixed-length columns, and all columns of secondary
@@ -2334,16 +2422,16 @@ dict_index_too_big_for_tree(
 			if (field->prefix_len < field_max_size) {
 				field_max_size = field->prefix_len;
 			}
-		} else if (field_max_size > BTR_EXTERN_FIELD_REF_SIZE * 2
+		} else if (field_max_size > BTR_EXTERN_LOCAL_STORED_MAX_SIZE
 			   && dict_index_is_clust(new_index)) {
 
 			/* In the worst case, we have a locally stored
-			column of BTR_EXTERN_FIELD_REF_SIZE * 2 bytes.
+			column of BTR_EXTERN_LOCAL_STORED_MAX_SIZE bytes.
 			The length can be stored in one byte.  If the
 			column were stored externally, the lengths in
 			the clustered index page would be
 			BTR_EXTERN_FIELD_REF_SIZE and 2. */
-			field_max_size = BTR_EXTERN_FIELD_REF_SIZE * 2;
+			field_max_size = BTR_EXTERN_LOCAL_STORED_MAX_SIZE;
 			field_ext_max_size = 1;
 		}
 
@@ -2486,7 +2574,7 @@ dict_index_add_to_cache(
 			= dict_field_get_col(field);
 
 		/* In dtuple_convert_big_rec(), variable-length columns
-		that are longer than BTR_EXTERN_FIELD_REF_SIZE * 2
+		that are longer than BTR_EXTERN_LOCAL_STORED_MAX_SIZE
 		may be chosen for external storage.  If the column appears
 		in an ordering column of an index, a longer prefix determined
 		by dict_max_field_len_store_undo() will be copied to the undo
@@ -2500,7 +2588,7 @@ dict_index_add_to_cache(
 			|| field->prefix_len > col->max_prefix)
 		    && !dict_col_get_fixed_size(col, TRUE) /* variable-length */
 		    && dict_col_get_max_size(col)
-		    > BTR_EXTERN_FIELD_REF_SIZE * 2 /* long enough */) {
+		    > BTR_EXTERN_LOCAL_STORED_MAX_SIZE /* long enough */) {
 
 			if (dict_index_too_big_for_undo(table, new_index)) {
 				/* An undo log record might not fit in
diff --git a/storage/innobase/dict/dict0stats.cc b/storage/innobase/dict/dict0stats.cc
index 001623a..840c622 100644
--- a/storage/innobase/dict/dict0stats.cc
+++ b/storage/innobase/dict/dict0stats.cc
@@ -1041,7 +1041,7 @@ dict_stats_analyze_index_level(
 		     index->table->name, index->name, level);
 
 	ut_ad(mtr_memo_contains(mtr, dict_index_get_lock(index),
-				MTR_MEMO_S_LOCK));
+				MTR_MEMO_SX_LOCK));
 
 	n_uniq = dict_index_get_n_unique(index);
 
@@ -1075,7 +1075,7 @@ dict_stats_analyze_index_level(
 	on the desired level. */
 
 	btr_pcur_open_at_index_side(
-		true, index, BTR_SEARCH_LEAF | BTR_ALREADY_S_LATCHED,
+		true, index, BTR_SEARCH_TREE | BTR_ALREADY_S_LATCHED,
 		&pcur, true, level, mtr);
 	btr_pcur_move_to_next_on_page(&pcur);
 
@@ -1691,13 +1691,13 @@ dict_stats_analyze_index_for_n_prefix(
 #endif
 
 	ut_ad(mtr_memo_contains(mtr, dict_index_get_lock(index),
-				MTR_MEMO_S_LOCK));
+				MTR_MEMO_SX_LOCK));
 
 	/* Position pcur on the leftmost record on the leftmost page
 	on the desired level. */
 
 	btr_pcur_open_at_index_side(
-		true, index, BTR_SEARCH_LEAF | BTR_ALREADY_S_LATCHED,
+		true, index, BTR_SEARCH_TREE | BTR_ALREADY_S_LATCHED,
 		&pcur, true, n_diff_data->level, mtr);
 	btr_pcur_move_to_next_on_page(&pcur);
 
@@ -1979,7 +1979,7 @@ dict_stats_analyze_index(
 
 	mtr_start(&mtr);
 
-	mtr_s_lock(dict_index_get_lock(index), &mtr);
+	mtr_sx_lock(dict_index_get_lock(index), &mtr);
 
 	root_level = btr_height_get(index, &mtr);
 
@@ -2066,7 +2066,7 @@ dict_stats_analyze_index(
 		other threads to do some work too. */
 		mtr_commit(&mtr);
 		mtr_start(&mtr);
-		mtr_s_lock(dict_index_get_lock(index), &mtr);
+		mtr_sx_lock(dict_index_get_lock(index), &mtr);
 		if (root_level != btr_height_get(index, &mtr)) {
 			/* Just quit if the tree has changed beyond
 			recognition here. The old stats from previous
diff --git a/storage/innobase/fsp/fsp0fsp.cc b/storage/innobase/fsp/fsp0fsp.cc
index ee1f2fd..7aa402c 100644
--- a/storage/innobase/fsp/fsp0fsp.cc
+++ b/storage/innobase/fsp/fsp0fsp.cc
@@ -156,11 +156,20 @@ fseg_alloc_free_page_low(
 				inserted there in order, into which
 				direction they go alphabetically: FSP_DOWN,
 				FSP_UP, FSP_NO_DIR */
+	rw_lock_type_t	rw_latch,/*!< in: RW_SX_LATCH, RW_X_LATCH */
 	mtr_t*		mtr,	/*!< in/out: mini-transaction */
-	mtr_t*		init_mtr)/*!< in/out: mtr or another 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. */
+#ifdef UNIV_DEBUG
+	,ibool has_done_reservation   /*!< in: TRUE if the caller has already
+				 done the reservation for the pages with
+				 fsp_reserve_free_extents (at least 2 extents: one for
+				 the inode and the other for the segment) then there is
+				 no need to do the check for this individual */
+#endif
+)
 	__attribute__((warn_unused_result, nonnull));
 #endif /* !UNIV_HOTBACKUP */
 
@@ -197,7 +206,7 @@ fsp_get_space_header(
 	ut_ad(!zip_size || zip_size >= UNIV_ZIP_SIZE_MIN);
 	ut_ad(id || !zip_size);
 
-	block = buf_page_get(id, zip_size, 0, RW_X_LATCH, mtr);
+	block = buf_page_get(id, zip_size, 0, RW_SX_LATCH, mtr);
 	header = FSP_HEADER_OFFSET + buf_block_get_frame(block);
 	buf_block_dbg_add_level(block, SYNC_FSP_PAGE);
 
@@ -221,7 +230,7 @@ xdes_mtr_get_bit(
 	mtr_t*		mtr)	/*!< in: mini-transaction */
 {
 	ut_ad(mtr->state == MTR_ACTIVE);
-	ut_ad(mtr_memo_contains_page(mtr, descr, MTR_MEMO_PAGE_X_FIX));
+	ut_ad(mtr_memo_contains_page(mtr, descr, MTR_MEMO_PAGE_SX_FIX));
 
 	return(xdes_get_bit(descr, bit, offset));
 }
@@ -244,7 +253,7 @@ xdes_set_bit(
 	ulint	bit_index;
 	ulint	descr_byte;
 
-	ut_ad(mtr_memo_contains_page(mtr, descr, MTR_MEMO_PAGE_X_FIX));
+	ut_ad(mtr_memo_contains_page(mtr, descr, MTR_MEMO_PAGE_SX_FIX));
 	ut_ad((bit == XDES_FREE_BIT) || (bit == XDES_CLEAN_BIT));
 	ut_ad(offset < FSP_EXTENT_SIZE);
 
@@ -282,7 +291,7 @@ xdes_find_bit(
 	ut_ad(descr && mtr);
 	ut_ad(val <= TRUE);
 	ut_ad(hint < FSP_EXTENT_SIZE);
-	ut_ad(mtr_memo_contains_page(mtr, descr, MTR_MEMO_PAGE_X_FIX));
+	ut_ad(mtr_memo_contains_page(mtr, descr, MTR_MEMO_PAGE_SX_FIX));
 	for (i = hint; i < FSP_EXTENT_SIZE; i++) {
 		if (val == xdes_mtr_get_bit(descr, bit, i, mtr)) {
 
@@ -320,7 +329,7 @@ xdes_find_bit_downward(
 	ut_ad(descr && mtr);
 	ut_ad(val <= TRUE);
 	ut_ad(hint < FSP_EXTENT_SIZE);
-	ut_ad(mtr_memo_contains_page(mtr, descr, MTR_MEMO_PAGE_X_FIX));
+	ut_ad(mtr_memo_contains_page(mtr, descr, MTR_MEMO_PAGE_SX_FIX));
 	for (i = hint + 1; i > 0; i--) {
 		if (val == xdes_mtr_get_bit(descr, bit, i - 1, mtr)) {
 
@@ -351,7 +360,7 @@ xdes_get_n_used(
 	ulint	count	= 0;
 
 	ut_ad(descr && mtr);
-	ut_ad(mtr_memo_contains_page(mtr, descr, MTR_MEMO_PAGE_X_FIX));
+	ut_ad(mtr_memo_contains_page(mtr, descr, MTR_MEMO_PAGE_SX_FIX));
 	for (ulint i = 0; i < FSP_EXTENT_SIZE; ++i) {
 		if (FALSE == xdes_mtr_get_bit(descr, XDES_FREE_BIT, i, mtr)) {
 			count++;
@@ -410,7 +419,7 @@ xdes_set_state(
 	ut_ad(descr && mtr);
 	ut_ad(state >= XDES_FREE);
 	ut_ad(state <= XDES_FSEG);
-	ut_ad(mtr_memo_contains_page(mtr, descr, MTR_MEMO_PAGE_X_FIX));
+	ut_ad(mtr_memo_contains_page(mtr, descr, MTR_MEMO_PAGE_SX_FIX));
 
 	mlog_write_ulint(descr + XDES_STATE, state, MLOG_4BYTES, mtr);
 }
@@ -428,7 +437,7 @@ xdes_get_state(
 	ulint	state;
 
 	ut_ad(descr && mtr);
-	ut_ad(mtr_memo_contains_page(mtr, descr, MTR_MEMO_PAGE_X_FIX));
+	ut_ad(mtr_memo_contains_page(mtr, descr, MTR_MEMO_PAGE_SX_FIX));
 
 	state = mtr_read_ulint(descr + XDES_STATE, MLOG_4BYTES, mtr);
 	ut_ad(state - 1 < XDES_FSEG);
@@ -447,7 +456,7 @@ xdes_init(
 	ulint	i;
 
 	ut_ad(descr && mtr);
-	ut_ad(mtr_memo_contains_page(mtr, descr, MTR_MEMO_PAGE_X_FIX));
+	ut_ad(mtr_memo_contains_page(mtr, descr, MTR_MEMO_PAGE_SX_FIX));
 	ut_ad((XDES_SIZE - XDES_BITMAP) % 4 == 0);
 
 	for (i = XDES_BITMAP; i < XDES_SIZE; i += 4) {
@@ -484,7 +493,7 @@ xdes_get_descriptor_with_space_hdr(
 
 	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_X_FIX));
+	ut_ad(mtr_memo_contains_page(mtr, sp_header, MTR_MEMO_PAGE_SX_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);
@@ -506,7 +515,7 @@ xdes_get_descriptor_with_space_hdr(
 		buf_block_t*	block;
 
 		block = buf_page_get(space, zip_size, descr_page_no,
-				     RW_X_LATCH, mtr);
+				     RW_SX_LATCH, mtr);
 		buf_block_dbg_add_level(block, SYNC_FSP_PAGE);
 
 		descr_page = buf_block_get_frame(block);
@@ -539,7 +548,7 @@ xdes_get_descriptor(
 	buf_block_t*	block;
 	fsp_header_t*	sp_header;
 
-	block = buf_page_get(space, zip_size, 0, RW_X_LATCH, mtr);
+	block = buf_page_get(space, zip_size, 0, RW_SX_LATCH, mtr);
 	buf_block_dbg_add_level(block, SYNC_FSP_PAGE);
 
 	sp_header = FSP_HEADER_OFFSET + buf_block_get_frame(block);
@@ -568,7 +577,7 @@ xdes_lst_get_descriptor(
 	ut_ad(mtr);
 	ut_ad(mtr_memo_contains(mtr, fil_space_get_latch(space, NULL),
 				MTR_MEMO_X_LOCK));
-	descr = fut_get_ptr(space, zip_size, lst_node, RW_X_LATCH, mtr)
+	descr = fut_get_ptr(space, zip_size, lst_node, RW_SX_LATCH, mtr)
 		- XDES_FLST_NODE;
 
 	return(descr);
@@ -729,7 +738,7 @@ fsp_header_init(
 
 	zip_size = fsp_flags_get_zip_size(flags);
 	block = buf_page_create(space, 0, zip_size, mtr);
-	buf_page_get(space, zip_size, 0, RW_X_LATCH, mtr);
+	buf_page_get(space, zip_size, 0, RW_SX_LATCH, mtr);
 	buf_block_dbg_add_level(block, SYNC_FSP_PAGE);
 
 	/* The prior contents of the file page should be ignored */
@@ -1145,7 +1154,7 @@ fsp_fill_free_list(
 				block = buf_page_create(
 					space, i, zip_size, mtr);
 				buf_page_get(space, zip_size, i,
-					     RW_X_LATCH, mtr);
+					     RW_SX_LATCH, mtr);
 				buf_block_dbg_add_level(block,
 							SYNC_FSP_PAGE);
 
@@ -1168,7 +1177,7 @@ fsp_fill_free_list(
 						    zip_size, &ibuf_mtr);
 			buf_page_get(space, zip_size,
 				     i + FSP_IBUF_BITMAP_OFFSET,
-				     RW_X_LATCH, &ibuf_mtr);
+					     RW_SX_LATCH, &ibuf_mtr);
 			buf_block_dbg_add_level(block, SYNC_FSP_PAGE);
 
 			fsp_init_file_page(block, &ibuf_mtr);
@@ -1313,6 +1322,7 @@ fsp_page_create(
 	ulint	zip_size,	/*!< in: compressed page size in bytes
 				or 0 for uncompressed pages */
 	ulint	page_no,	/*!< in: page number of the allocated page */
+	rw_lock_type_t rw_latch,/*!< in: RW_SX_LATCH, RW_X_LATCH */
 	mtr_t*	mtr,		/*!< in: mini-transaction of the allocation */
 	mtr_t*	init_mtr)	/*!< in: mini-transaction for initializing
 				the page */
@@ -1322,23 +1332,35 @@ fsp_page_create(
 #ifdef UNIV_SYNC_DEBUG
 	ut_ad(mtr_memo_contains(mtr, block, MTR_MEMO_PAGE_X_FIX)
 	      == rw_lock_own(&block->lock, RW_LOCK_EX));
+	ut_ad(mtr_memo_contains(mtr, block, MTR_MEMO_PAGE_SX_FIX)
+	      == rw_lock_own(&block->lock, RW_LOCK_SX));
 #endif /* UNIV_SYNC_DEBUG */
+	ut_ad(rw_latch == RW_X_LATCH || rw_latch == RW_SX_LATCH);
 
 	/* Mimic buf_page_get(), but avoid the buf_pool->page_hash lookup. */
-	rw_lock_x_lock(&block->lock);
+	if (rw_latch == RW_X_LATCH) {
+		rw_lock_x_lock(&block->lock);
+	} else {
+		rw_lock_sx_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);
+	mtr_memo_push(init_mtr, block, rw_latch == RW_X_LATCH
+		      ? MTR_MEMO_PAGE_X_FIX : MTR_MEMO_PAGE_SX_FIX);
 
 	if (init_mtr == mtr
-	    || rw_lock_get_x_lock_count(&block->lock) == 1) {
+	    || (rw_latch == RW_X_LATCH
+		? rw_lock_get_x_lock_count(&block->lock) == 1
+		: rw_lock_get_sx_lock_count(&block->lock) == 1)) {
 
 		/* Initialize the page, unless it was already
-		X-latched in mtr. (In this case, we would want to
+		SX-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));
+		      || !mtr_memo_contains_flagged(mtr, block,
+						    MTR_MEMO_PAGE_X_FIX
+						    | MTR_MEMO_PAGE_SX_FIX));
 
 		fsp_init_file_page(block, init_mtr);
 	}
@@ -1360,6 +1382,7 @@ fsp_alloc_free_page(
 	ulint	zip_size,/*!< in: compressed page size in bytes
 			or 0 for uncompressed pages */
 	ulint	hint,	/*!< in: hint of which page would be desirable */
+	rw_lock_type_t rw_latch,/*!< in: RW_SX_LATCH, RW_X_LATCH */
 	mtr_t*	mtr,	/*!< in/out: mini-transaction */
 	mtr_t*	init_mtr)/*!< in/out: mini-transaction in which the
 			page should be initialized
@@ -1455,7 +1478,8 @@ fsp_alloc_free_page(
 	}
 
 	fsp_alloc_from_free_frag(header, descr, free, mtr);
-	return(fsp_page_create(space, zip_size, page_no, mtr, init_mtr));
+	return(fsp_page_create(space, zip_size, page_no,
+			       rw_latch, mtr, init_mtr));
 }
 
 /**********************************************************************//**
@@ -1607,7 +1631,7 @@ fsp_seg_inode_page_get_nth_inode(
 			/*!< in/out: mini-transaction */
 {
 	ut_ad(i < FSP_SEG_INODES_PER_PAGE(zip_size));
-	ut_ad(mtr_memo_contains_page(mtr, page, MTR_MEMO_PAGE_X_FIX));
+	ut_ad(mtr_memo_contains_page(mtr, page, MTR_MEMO_PAGE_SX_FIX));
 
 	return(page + FSEG_ARR_OFFSET + FSEG_INODE_SIZE * i);
 }
@@ -1697,7 +1721,7 @@ fsp_alloc_seg_inode_page(
 	zip_size = fsp_flags_get_zip_size(
 		mach_read_from_4(FSP_SPACE_FLAGS + space_header));
 
-	block = fsp_alloc_free_page(space, zip_size, 0, mtr, mtr);
+	block = fsp_alloc_free_page(space, zip_size, 0, RW_SX_LATCH, mtr, mtr);
 
 	if (block == NULL) {
 
@@ -1705,7 +1729,7 @@ fsp_alloc_seg_inode_page(
 	}
 
 	buf_block_dbg_add_level(block, SYNC_FSP_PAGE);
-	ut_ad(rw_lock_get_x_lock_count(&block->lock) == 1);
+	ut_ad(rw_lock_get_sx_lock_count(&block->lock) == 1);
 
 	block->check_index_page_at_flush = FALSE;
 
@@ -1765,7 +1789,7 @@ fsp_alloc_seg_inode(
 	zip_size = fsp_flags_get_zip_size(
 		mach_read_from_4(FSP_SPACE_FLAGS + space_header));
 	block = buf_page_get(page_get_space_id(page_align(space_header)),
-			     zip_size, page_no, RW_X_LATCH, mtr);
+			     zip_size, page_no, RW_SX_LATCH, mtr);
 	buf_block_dbg_add_level(block, SYNC_FSP_PAGE);
 
 	page = buf_block_get_frame(block);
@@ -1861,7 +1885,7 @@ fseg_inode_try_get(
 	inode_addr.boffset = mach_read_from_2(header + FSEG_HDR_OFFSET);
 	ut_ad(space == mach_read_from_4(header + FSEG_HDR_SPACE));
 
-	inode = fut_get_ptr(space, zip_size, inode_addr, RW_X_LATCH, mtr);
+	inode = fut_get_ptr(space, zip_size, inode_addr, RW_SX_LATCH, mtr);
 
 	if (UNIV_UNLIKELY(!mach_read_from_8(inode + FSEG_ID))) {
 
@@ -1907,7 +1931,7 @@ fseg_get_nth_frag_page_no(
 {
 	ut_ad(inode && mtr);
 	ut_ad(n < FSEG_FRAG_ARR_N_SLOTS);
-	ut_ad(mtr_memo_contains_page(mtr, inode, MTR_MEMO_PAGE_X_FIX));
+	ut_ad(mtr_memo_contains_page(mtr, inode, MTR_MEMO_PAGE_SX_FIX));
 	ut_ad(mach_read_from_4(inode + FSEG_MAGIC_N) == FSEG_MAGIC_N_VALUE);
 	return(mach_read_from_4(inode + FSEG_FRAG_ARR
 				+ n * FSEG_FRAG_SLOT_SIZE));
@@ -1926,7 +1950,7 @@ fseg_set_nth_frag_page_no(
 {
 	ut_ad(inode && mtr);
 	ut_ad(n < FSEG_FRAG_ARR_N_SLOTS);
-	ut_ad(mtr_memo_contains_page(mtr, inode, MTR_MEMO_PAGE_X_FIX));
+	ut_ad(mtr_memo_contains_page(mtr, inode, MTR_MEMO_PAGE_SX_FIX));
 	ut_ad(mach_read_from_4(inode + FSEG_MAGIC_N) == FSEG_MAGIC_N_VALUE);
 
 	mlog_write_ulint(inode + FSEG_FRAG_ARR + n * FSEG_FRAG_SLOT_SIZE,
@@ -2055,7 +2079,7 @@ fseg_create_general(
 	zip_size = fsp_flags_get_zip_size(flags);
 
 	if (page != 0) {
-		block = buf_page_get(space, zip_size, page, RW_X_LATCH, mtr);
+		block = buf_page_get(space, zip_size, page, RW_SX_LATCH, mtr);
 		header = byte_offset + buf_block_get_frame(block);
 	}
 
@@ -2109,7 +2133,16 @@ fseg_create_general(
 
 	if (page == 0) {
 		block = fseg_alloc_free_page_low(space, zip_size,
-						 inode, 0, FSP_UP, mtr, mtr);
+						 inode, 0, FSP_UP, RW_SX_LATCH,
+						 mtr, mtr
+#ifdef UNIV_DEBUG
+						 , has_done_reservation
+#endif
+						 );
+
+		/* The allocation cannot fail if we have already reserved a
+		space for the page. */
+		ut_ad(!has_done_reservation || block != NULL);
 
 		if (block == NULL) {
 
@@ -2118,7 +2151,7 @@ fseg_create_general(
 			goto funct_exit;
 		}
 
-		ut_ad(rw_lock_get_x_lock_count(&block->lock) == 1);
+		ut_ad(rw_lock_get_sx_lock_count(&block->lock) == 1);
 
 		header = byte_offset + buf_block_get_frame(block);
 		mlog_write_ulint(buf_block_get_frame(block) + FIL_PAGE_TYPE,
@@ -2179,7 +2212,7 @@ fseg_n_reserved_pages_low(
 	ulint	ret;
 
 	ut_ad(inode && used && mtr);
-	ut_ad(mtr_memo_contains_page(mtr, inode, MTR_MEMO_PAGE_X_FIX));
+	ut_ad(mtr_memo_contains_page(mtr, inode, MTR_MEMO_PAGE_SX_FIX));
 
 	*used = mtr_read_ulint(inode + FSEG_NOT_FULL_N_USED, MLOG_4BYTES, mtr)
 		+ FSP_EXTENT_SIZE * flst_get_len(inode + FSEG_FULL, mtr)
@@ -2369,11 +2402,20 @@ fseg_alloc_free_page_low(
 				inserted there in order, into which
 				direction they go alphabetically: FSP_DOWN,
 				FSP_UP, FSP_NO_DIR */
+	rw_lock_type_t	rw_latch,/*!< in: RW_SX_LATCH, RW_X_LATCH */
 	mtr_t*		mtr,	/*!< in/out: mini-transaction */
-	mtr_t*		init_mtr)/*!< in/out: mtr or another 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. */
+#ifdef UNIV_DEBUG
+	,ibool has_done_reservation   /*!< in: TRUE if the caller has already
+				 done the reservation for the pages with
+				 fsp_reserve_free_extents (at least 2 extents: one for
+				 the inode and the other for the segment) then there is
+				 no need to do the check for this individual */
+#endif
+)
 {
 	fsp_header_t*	space_header;
 	ulint		space_size;
@@ -2466,6 +2508,7 @@ fseg_alloc_free_page_low(
 		if (direction == FSP_DOWN) {
 			ret_page += FSP_EXTENT_SIZE - 1;
 		}
+		ut_ad(!has_done_reservation || ret_page != FIL_NULL);
 		/*-----------------------------------------------------------*/
 	} else if ((xdes_get_state(descr, mtr) == XDES_FSEG)
 		   && mach_read_from_8(descr + XDES_ID) == seg_id
@@ -2481,6 +2524,7 @@ fseg_alloc_free_page_low(
 		ret_page = xdes_get_offset(ret_descr)
 			+ xdes_find_bit(ret_descr, XDES_FREE_BIT, TRUE,
 					hint % FSP_EXTENT_SIZE, mtr);
+		ut_ad(!has_done_reservation || ret_page != FIL_NULL);
 		/*-----------------------------------------------------------*/
 	} else if (reserved - used > 0) {
 		/* 5. We take any unused page from the segment
@@ -2502,12 +2546,15 @@ fseg_alloc_free_page_low(
 		ret_page = xdes_get_offset(ret_descr)
 			+ xdes_find_bit(ret_descr, XDES_FREE_BIT, TRUE,
 					0, mtr);
+		ut_ad(!has_done_reservation || ret_page != FIL_NULL);
 		/*-----------------------------------------------------------*/
 	} else if (used < FSEG_FRAG_LIMIT) {
 		/* 6. We allocate an individual page from the space
 		===================================================*/
 		buf_block_t* block = fsp_alloc_free_page(
-			space, zip_size, hint, mtr, init_mtr);
+			space, zip_size, hint, rw_latch, mtr, init_mtr);
+
+		ut_ad(!has_done_reservation || block != NULL);
 
 		if (block != NULL) {
 			/* Put the page in the fragment page array of the
@@ -2532,14 +2579,17 @@ fseg_alloc_free_page_low(
 
 		if (ret_descr == NULL) {
 			ret_page = FIL_NULL;
+			ut_ad(!has_done_reservation);
 		} else {
 			ret_page = xdes_get_offset(ret_descr);
+			ut_ad(!has_done_reservation || ret_page != FIL_NULL);
 		}
 	}
 
 	if (ret_page == FIL_NULL) {
 		/* Page could not be allocated */
 
+		ut_ad(!has_done_reservation);
 		return(NULL);
 	}
 
@@ -2558,6 +2608,7 @@ fseg_alloc_free_page_low(
 					" the space size %lu. Page no %lu.\n",
 					(ulong) space, (ulong) space_size,
 					(ulong) ret_page);
+				ut_ad(!has_done_reservation);
 				return(NULL);
 			}
 
@@ -2565,6 +2616,7 @@ fseg_alloc_free_page_low(
 				space, ret_page, space_header, mtr);
 			if (!success) {
 				/* No disk space left */
+				ut_ad(!has_done_reservation);
 				return(NULL);
 			}
 		}
@@ -2592,7 +2644,7 @@ fseg_alloc_free_page_low(
 		       space, fsp_flags_get_zip_size(
 			       mach_read_from_4(FSP_SPACE_FLAGS
 						+ space_header)),
-		       ret_page, mtr, init_mtr));
+		       ret_page, rw_latch, mtr, init_mtr));
 }
 
 /**********************************************************************//**
@@ -2661,7 +2713,16 @@ fseg_alloc_free_page_general(
 
 	block = fseg_alloc_free_page_low(space, zip_size,
 					 inode, hint, direction,
-					 mtr, init_mtr);
+					 RW_X_LATCH, mtr, init_mtr
+#ifdef UNIV_DEBUG
+					 , has_done_reservation
+#endif
+					 );
+
+	/* The allocation cannot fail if we have already reserved a
+	space for the page. */
+	ut_ad(!has_done_reservation || block != NULL);
+
 	if (!has_done_reservation) {
 		fil_space_release_free_extents(space, n_reserved);
 	}
@@ -3530,7 +3591,7 @@ fseg_validate_low(
 	ulint		n_used		= 0;
 	ulint		n_used2		= 0;
 
-	ut_ad(mtr_memo_contains_page(mtr2, inode, MTR_MEMO_PAGE_X_FIX));
+	ut_ad(mtr_memo_contains_page(mtr2, inode, MTR_MEMO_PAGE_SX_FIX));
 	ut_ad(mach_read_from_4(inode + FSEG_MAGIC_N) == FSEG_MAGIC_N_VALUE);
 
 	space = page_get_space_id(page_align(inode));
@@ -3668,7 +3729,7 @@ fseg_print_low(
 	ulint	page_no;
 	ib_id_t	seg_id;
 
-	ut_ad(mtr_memo_contains_page(mtr, inode, MTR_MEMO_PAGE_X_FIX));
+	ut_ad(mtr_memo_contains_page(mtr, inode, MTR_MEMO_PAGE_SX_FIX));
 	space = page_get_space_id(page_align(inode));
 	page_no = page_get_page_no(page_align(inode));
 
@@ -3885,7 +3946,7 @@ fsp_validate(
 			mtr_x_lock(latch, &mtr);
 
 			seg_inode_page = fut_get_ptr(
-				space, zip_size, node_addr, RW_X_LATCH, &mtr)
+				space, zip_size, node_addr, RW_SX_LATCH, &mtr)
 				- FSEG_INODE_PAGE_NODE;
 
 			seg_inode = fsp_seg_inode_page_get_nth_inode(
@@ -3930,7 +3991,7 @@ fsp_validate(
 			mtr_x_lock(latch, &mtr);
 
 			seg_inode_page = fut_get_ptr(
-				space, zip_size, node_addr, RW_X_LATCH, &mtr)
+				space, zip_size, node_addr, RW_SX_LATCH, &mtr)
 				- FSEG_INODE_PAGE_NODE;
 
 			seg_inode = fsp_seg_inode_page_get_nth_inode(
@@ -4065,7 +4126,7 @@ fsp_print(
 			mtr_x_lock(latch, &mtr);
 
 			seg_inode_page = fut_get_ptr(
-				space, zip_size, node_addr, RW_X_LATCH, &mtr)
+				space, zip_size, node_addr, RW_SX_LATCH, &mtr)
 				- FSEG_INODE_PAGE_NODE;
 
 			seg_inode = fsp_seg_inode_page_get_nth_inode(
@@ -4102,7 +4163,7 @@ fsp_print(
 			mtr_x_lock(latch, &mtr);
 
 			seg_inode_page = fut_get_ptr(
-				space, zip_size, node_addr, RW_X_LATCH, &mtr)
+				space, zip_size, node_addr, RW_SX_LATCH, &mtr)
 				- FSEG_INODE_PAGE_NODE;
 
 			seg_inode = fsp_seg_inode_page_get_nth_inode(
diff --git a/storage/innobase/fut/fut0lst.cc b/storage/innobase/fut/fut0lst.cc
index 8f96a64..3ef18e0 100644
--- a/storage/innobase/fut/fut0lst.cc
+++ b/storage/innobase/fut/fut0lst.cc
@@ -49,8 +49,12 @@ flst_add_to_empty(
 
 	ut_ad(mtr && base && node);
 	ut_ad(base != node);
-	ut_ad(mtr_memo_contains_page(mtr, base, MTR_MEMO_PAGE_X_FIX));
-	ut_ad(mtr_memo_contains_page(mtr, node, MTR_MEMO_PAGE_X_FIX));
+	ut_ad(mtr_memo_contains_page_flagged(mtr, base,
+					     MTR_MEMO_PAGE_X_FIX
+					     | MTR_MEMO_PAGE_SX_FIX));
+	ut_ad(mtr_memo_contains_page_flagged(mtr, node,
+					     MTR_MEMO_PAGE_X_FIX
+					     | MTR_MEMO_PAGE_SX_FIX));
 	len = flst_get_len(base, mtr);
 	ut_a(len == 0);
 
@@ -86,8 +90,12 @@ flst_add_last(
 
 	ut_ad(mtr && base && node);
 	ut_ad(base != node);
-	ut_ad(mtr_memo_contains_page(mtr, base, MTR_MEMO_PAGE_X_FIX));
-	ut_ad(mtr_memo_contains_page(mtr, node, MTR_MEMO_PAGE_X_FIX));
+	ut_ad(mtr_memo_contains_page_flagged(mtr, base,
+					     MTR_MEMO_PAGE_X_FIX
+					     | MTR_MEMO_PAGE_SX_FIX));
+	ut_ad(mtr_memo_contains_page_flagged(mtr, node,
+					     MTR_MEMO_PAGE_X_FIX
+					     | MTR_MEMO_PAGE_SX_FIX));
 	len = flst_get_len(base, mtr);
 	last_addr = flst_get_last(base, mtr);
 
@@ -101,7 +109,7 @@ flst_add_last(
 			ulint	zip_size = fil_space_get_zip_size(space);
 
 			last_node = fut_get_ptr(space, zip_size, last_addr,
-						RW_X_LATCH, mtr);
+						RW_SX_LATCH, mtr);
 		}
 
 		flst_insert_after(base, last_node, node, mtr);
@@ -129,8 +137,12 @@ flst_add_first(
 
 	ut_ad(mtr && base && node);
 	ut_ad(base != node);
-	ut_ad(mtr_memo_contains_page(mtr, base, MTR_MEMO_PAGE_X_FIX));
-	ut_ad(mtr_memo_contains_page(mtr, node, MTR_MEMO_PAGE_X_FIX));
+	ut_ad(mtr_memo_contains_page_flagged(mtr, base,
+					     MTR_MEMO_PAGE_X_FIX
+					     | MTR_MEMO_PAGE_SX_FIX));
+	ut_ad(mtr_memo_contains_page_flagged(mtr, node,
+					     MTR_MEMO_PAGE_X_FIX
+					     | MTR_MEMO_PAGE_SX_FIX));
 	len = flst_get_len(base, mtr);
 	first_addr = flst_get_first(base, mtr);
 
@@ -144,7 +156,7 @@ flst_add_first(
 			ulint	zip_size = fil_space_get_zip_size(space);
 
 			first_node = fut_get_ptr(space, zip_size, first_addr,
-						 RW_X_LATCH, mtr);
+						 RW_SX_LATCH, mtr);
 		}
 
 		flst_insert_before(base, node, first_node, mtr);
@@ -176,9 +188,15 @@ flst_insert_after(
 	ut_ad(base != node1);
 	ut_ad(base != node2);
 	ut_ad(node2 != node1);
-	ut_ad(mtr_memo_contains_page(mtr, base, MTR_MEMO_PAGE_X_FIX));
-	ut_ad(mtr_memo_contains_page(mtr, node1, MTR_MEMO_PAGE_X_FIX));
-	ut_ad(mtr_memo_contains_page(mtr, node2, MTR_MEMO_PAGE_X_FIX));
+	ut_ad(mtr_memo_contains_page_flagged(mtr, base,
+					     MTR_MEMO_PAGE_X_FIX
+					     | MTR_MEMO_PAGE_SX_FIX));
+	ut_ad(mtr_memo_contains_page_flagged(mtr, node1,
+					     MTR_MEMO_PAGE_X_FIX
+					     | MTR_MEMO_PAGE_SX_FIX));
+	ut_ad(mtr_memo_contains_page_flagged(mtr, node2,
+					     MTR_MEMO_PAGE_X_FIX
+					     | MTR_MEMO_PAGE_SX_FIX));
 
 	buf_ptr_get_fsp_addr(node1, &space, &node1_addr);
 	buf_ptr_get_fsp_addr(node2, &space, &node2_addr);
@@ -194,7 +212,7 @@ flst_insert_after(
 		ulint	zip_size = fil_space_get_zip_size(space);
 
 		node3 = fut_get_ptr(space, zip_size,
-				    node3_addr, RW_X_LATCH, mtr);
+				    node3_addr, RW_SX_LATCH, mtr);
 		flst_write_addr(node3 + FLST_PREV, node2_addr, mtr);
 	} else {
 		/* node1 was last in list: update last field in base */
@@ -231,9 +249,15 @@ flst_insert_before(
 	ut_ad(base != node2);
 	ut_ad(base != node3);
 	ut_ad(node2 != node3);
-	ut_ad(mtr_memo_contains_page(mtr, base, MTR_MEMO_PAGE_X_FIX));
-	ut_ad(mtr_memo_contains_page(mtr, node2, MTR_MEMO_PAGE_X_FIX));
-	ut_ad(mtr_memo_contains_page(mtr, node3, MTR_MEMO_PAGE_X_FIX));
+	ut_ad(mtr_memo_contains_page_flagged(mtr, base,
+					     MTR_MEMO_PAGE_X_FIX
+					     | MTR_MEMO_PAGE_SX_FIX));
+	ut_ad(mtr_memo_contains_page_flagged(mtr, node2,
+					     MTR_MEMO_PAGE_X_FIX
+					     | MTR_MEMO_PAGE_SX_FIX));
+	ut_ad(mtr_memo_contains_page_flagged(mtr, node3,
+					     MTR_MEMO_PAGE_X_FIX
+					     | MTR_MEMO_PAGE_SX_FIX));
 
 	buf_ptr_get_fsp_addr(node2, &space, &node2_addr);
 	buf_ptr_get_fsp_addr(node3, &space, &node3_addr);
@@ -248,7 +272,7 @@ flst_insert_before(
 		ulint	zip_size = fil_space_get_zip_size(space);
 		/* Update next field of node1 */
 		node1 = fut_get_ptr(space, zip_size, node1_addr,
-				    RW_X_LATCH, mtr);
+				    RW_SX_LATCH, mtr);
 		flst_write_addr(node1 + FLST_NEXT, node2_addr, mtr);
 	} else {
 		/* node3 was first in list: update first field in base */
@@ -283,8 +307,12 @@ flst_remove(
 	ulint		len;
 
 	ut_ad(mtr && node2 && base);
-	ut_ad(mtr_memo_contains_page(mtr, base, MTR_MEMO_PAGE_X_FIX));
-	ut_ad(mtr_memo_contains_page(mtr, node2, MTR_MEMO_PAGE_X_FIX));
+	ut_ad(mtr_memo_contains_page_flagged(mtr, base,
+					     MTR_MEMO_PAGE_X_FIX
+					     | MTR_MEMO_PAGE_SX_FIX));
+	ut_ad(mtr_memo_contains_page_flagged(mtr, node2,
+					     MTR_MEMO_PAGE_X_FIX
+					     | MTR_MEMO_PAGE_SX_FIX));
 
 	buf_ptr_get_fsp_addr(node2, &space, &node2_addr);
 	zip_size = fil_space_get_zip_size(space);
@@ -301,7 +329,7 @@ flst_remove(
 			node1 = page_align(node2) + node1_addr.boffset;
 		} else {
 			node1 = fut_get_ptr(space, zip_size,
-					    node1_addr, RW_X_LATCH, mtr);
+					    node1_addr, RW_SX_LATCH, mtr);
 		}
 
 		ut_ad(node1 != node2);
@@ -320,7 +348,7 @@ flst_remove(
 			node3 = page_align(node2) + node3_addr.boffset;
 		} else {
 			node3 = fut_get_ptr(space, zip_size,
-					    node3_addr, RW_X_LATCH, mtr);
+					    node3_addr, RW_SX_LATCH, mtr);
 		}
 
 		ut_ad(node2 != node3);
@@ -359,8 +387,12 @@ flst_cut_end(
 	ulint		len;
 
 	ut_ad(mtr && node2 && base);
-	ut_ad(mtr_memo_contains_page(mtr, base, MTR_MEMO_PAGE_X_FIX));
-	ut_ad(mtr_memo_contains_page(mtr, node2, MTR_MEMO_PAGE_X_FIX));
+	ut_ad(mtr_memo_contains_page_flagged(mtr, base,
+					     MTR_MEMO_PAGE_X_FIX
+					     | MTR_MEMO_PAGE_SX_FIX));
+	ut_ad(mtr_memo_contains_page_flagged(mtr, node2,
+					     MTR_MEMO_PAGE_X_FIX
+					     | MTR_MEMO_PAGE_SX_FIX));
 	ut_ad(n_nodes > 0);
 
 	buf_ptr_get_fsp_addr(node2, &space, &node2_addr);
@@ -377,7 +409,7 @@ flst_cut_end(
 		} else {
 			node1 = fut_get_ptr(space,
 					    fil_space_get_zip_size(space),
-					    node1_addr, RW_X_LATCH, mtr);
+					    node1_addr, RW_SX_LATCH, mtr);
 		}
 
 		flst_write_addr(node1 + FLST_NEXT, fil_addr_null, mtr);
@@ -413,8 +445,12 @@ flst_truncate_end(
 	ulint		space;
 
 	ut_ad(mtr && node2 && base);
-	ut_ad(mtr_memo_contains_page(mtr, base, MTR_MEMO_PAGE_X_FIX));
-	ut_ad(mtr_memo_contains_page(mtr, node2, MTR_MEMO_PAGE_X_FIX));
+	ut_ad(mtr_memo_contains_page_flagged(mtr, base,
+					     MTR_MEMO_PAGE_X_FIX
+					     | MTR_MEMO_PAGE_SX_FIX));
+	ut_ad(mtr_memo_contains_page_flagged(mtr, node2,
+					     MTR_MEMO_PAGE_X_FIX
+					     | MTR_MEMO_PAGE_SX_FIX));
 	if (n_nodes == 0) {
 
 		ut_ad(fil_addr_is_null(flst_get_next_addr(node2, mtr)));
@@ -456,7 +492,9 @@ flst_validate(
 	mtr_t			mtr2;
 
 	ut_ad(base);
-	ut_ad(mtr_memo_contains_page(mtr1, base, MTR_MEMO_PAGE_X_FIX));
+	ut_ad(mtr_memo_contains_page_flagged(mtr1, base,
+					     MTR_MEMO_PAGE_X_FIX
+					     | MTR_MEMO_PAGE_SX_FIX));
 
 	/* We use two mini-transaction handles: the first is used to
 	lock the base node, and prevent other threads from modifying the
@@ -476,7 +514,7 @@ flst_validate(
 		mtr_start(&mtr2);
 
 		node = fut_get_ptr(space, zip_size,
-				   node_addr, RW_X_LATCH, &mtr2);
+				   node_addr, RW_SX_LATCH, &mtr2);
 		node_addr = flst_get_next_addr(node, &mtr2);
 
 		mtr_commit(&mtr2); /* Commit mtr2 each round to prevent buffer
@@ -491,7 +529,7 @@ flst_validate(
 		mtr_start(&mtr2);
 
 		node = fut_get_ptr(space, zip_size,
-				   node_addr, RW_X_LATCH, &mtr2);
+				   node_addr, RW_SX_LATCH, &mtr2);
 		node_addr = flst_get_prev_addr(node, &mtr2);
 
 		mtr_commit(&mtr2); /* Commit mtr2 each round to prevent buffer
@@ -516,7 +554,9 @@ flst_print(
 	ulint			len;
 
 	ut_ad(base && mtr);
-	ut_ad(mtr_memo_contains_page(mtr, base, MTR_MEMO_PAGE_X_FIX));
+	ut_ad(mtr_memo_contains_page_flagged(mtr, base,
+					     MTR_MEMO_PAGE_X_FIX
+					     | MTR_MEMO_PAGE_SX_FIX));
 	frame = page_align((byte*) base);
 
 	len = flst_get_len(base, mtr);
diff --git a/storage/innobase/handler/ha_innodb.cc b/storage/innobase/handler/ha_innodb.cc
index 3a5f961..e716c93 100644
--- a/storage/innobase/handler/ha_innodb.cc
+++ b/storage/innobase/handler/ha_innodb.cc
@@ -13407,7 +13407,7 @@ ha_innobase::check(
 				server_mutex,
                                 srv_fatal_semaphore_wait_threshold,
 				SRV_SEMAPHORE_WAIT_EXTENSION);
-			bool valid = btr_validate_index(index, prebuilt->trx);
+			bool valid = btr_validate_index(index, prebuilt->trx, true);
 
 			/* Restore the fatal lock wait timeout after
 			CHECK TABLE. */
diff --git a/storage/innobase/ibuf/ibuf0ibuf.cc b/storage/innobase/ibuf/ibuf0ibuf.cc
index 5fd0fdc..ad8a454 100644
--- a/storage/innobase/ibuf/ibuf0ibuf.cc
+++ b/storage/innobase/ibuf/ibuf0ibuf.cc
@@ -406,10 +406,11 @@ ibuf_tree_root_get(
 	ut_ad(ibuf_inside(mtr));
 	ut_ad(mutex_own(&ibuf_mutex));
 
-	mtr_x_lock(dict_index_get_lock(ibuf->index), mtr);
+	mtr_sx_lock(dict_index_get_lock(ibuf->index), mtr);
 
+	/* only segment list access is exclusive each other */
 	block = buf_page_get(
-		IBUF_SPACE_ID, 0, FSP_IBUF_TREE_ROOT_PAGE_NO, RW_X_LATCH, mtr);
+		IBUF_SPACE_ID, 0, FSP_IBUF_TREE_ROOT_PAGE_NO, RW_SX_LATCH, mtr);
 
 	buf_block_dbg_add_level(block, SYNC_IBUF_TREE_NODE_NEW);
 
@@ -3543,7 +3544,7 @@ ibuf_insert_low(
 	the new entry to it without exceeding the free space limit for the
 	page. */
 
-	if (mode == BTR_MODIFY_TREE) {
+	if (BTR_LATCH_MODE_WITHOUT_INTENTION(mode) == BTR_MODIFY_TREE) {
 		for (;;) {
 			mutex_enter(&ibuf_pessimistic_insert_mutex);
 			mutex_enter(&ibuf_mutex);
@@ -3598,7 +3599,7 @@ ibuf_insert_low(
 		until after the IBUF_OP_DELETE has been buffered. */
 
 fail_exit:
-		if (mode == BTR_MODIFY_TREE) {
+		if (BTR_LATCH_MODE_WITHOUT_INTENTION(mode) == BTR_MODIFY_TREE) {
 			mutex_exit(&ibuf_mutex);
 			mutex_exit(&ibuf_pessimistic_insert_mutex);
 		}
@@ -3715,7 +3716,8 @@ ibuf_insert_low(
 			ibuf->empty = page_is_empty(root);
 		}
 	} else {
-		ut_ad(mode == BTR_MODIFY_TREE);
+		ut_ad(BTR_LATCH_MODE_WITHOUT_INTENTION(mode)
+		      == BTR_MODIFY_TREE);
 
 		/* We acquire an x-latch to the root page before the insert,
 		because a pessimistic insert releases the tree x-latch,
@@ -3775,7 +3777,8 @@ ibuf_insert_low(
 
 	mem_heap_free(heap);
 
-	if (err == DB_SUCCESS && mode == BTR_MODIFY_TREE) {
+	if (err == DB_SUCCESS
+	    && BTR_LATCH_MODE_WITHOUT_INTENTION(mode) == BTR_MODIFY_TREE) {
 		ibuf_contract_after_insert(entry_size);
 	}
 
@@ -3920,8 +3923,8 @@ ibuf_insert(
 			      entry, entry_size,
 			      index, space, zip_size, page_no, thr);
 	if (err == DB_FAIL) {
-		err = ibuf_insert_low(BTR_MODIFY_TREE, op, no_counter,
-				      entry, entry_size,
+		err = ibuf_insert_low(BTR_MODIFY_TREE | BTR_LATCH_FOR_INSERT,
+				      op, no_counter, entry, entry_size,
 				      index, space, zip_size, page_no, thr);
 	}
 
@@ -4388,7 +4391,8 @@ ibuf_restore_pos(
 				position is to be restored */
 	mtr_t*		mtr)	/*!< in/out: mini-transaction */
 {
-	ut_ad(mode == BTR_MODIFY_LEAF || mode == BTR_MODIFY_TREE);
+	ut_ad(mode == BTR_MODIFY_LEAF
+	      || BTR_LATCH_MODE_WITHOUT_INTENTION(mode) == BTR_MODIFY_TREE);
 
 	if (btr_pcur_restore_position(mode, pcur, mtr)) {
 
@@ -4418,7 +4422,14 @@ ibuf_restore_pos(
 		fflush(stderr);
 
 		ibuf_btr_pcur_commit_specify_mtr(pcur, mtr);
-		ut_ad(0);
+
+		ib_logf(IB_LOG_LEVEL_INFO, "Validating insert buffer tree:");
+		if (!btr_validate_index(ibuf->index, 0, false)) {
+			ut_error;
+		}
+		ib_logf(IB_LOG_LEVEL_INFO, "ibuf tree is OK.");
+
+		ib_logf(IB_LOG_LEVEL_FATAL, "Failed to restore ibuf position.");
 	}
 
 	return(FALSE);
@@ -4516,7 +4527,8 @@ ibuf_delete_rec(
 	mutex_enter(&ibuf_mutex);
 
 	if (!ibuf_restore_pos(space, page_no, search_tuple,
-			      BTR_MODIFY_TREE, pcur, mtr)) {
+			      BTR_MODIFY_TREE | BTR_LATCH_FOR_DELETE,
+			      pcur, mtr)) {
 
 		mutex_exit(&ibuf_mutex);
 		ut_ad(mtr->state == MTR_COMMITTED);
diff --git a/storage/innobase/include/btr0btr.h b/storage/innobase/include/btr0btr.h
index 3cd44e3..647ee7b 100644
--- a/storage/innobase/include/btr0btr.h
+++ b/storage/innobase/include/btr0btr.h
@@ -67,7 +67,11 @@ enum btr_latch_mode {
 	/** Search the previous record. */
 	BTR_SEARCH_PREV = 35,
 	/** Modify the previous record. */
-	BTR_MODIFY_PREV = 36
+	BTR_MODIFY_PREV = 36,
+	/** Start searching the entire B-tree. */
+	BTR_SEARCH_TREE = 37,
+	/** Continue searching the entire B-tree. */
+	BTR_CONT_SEARCH_TREE = 38
 };
 
 /* BTR_INSERT, BTR_DELETE and BTR_DELETE_MARK are mutually exclusive. */
@@ -98,13 +102,27 @@ buffer when the record is not in the buffer pool. */
 already holding an S latch on the index tree */
 #define BTR_ALREADY_S_LATCHED	16384
 
+/** In the case of BTR_MODIFY_TREE, the caller specifies the intention
+to insert record only. It is used to optimize block->lock range.*/
+#define BTR_LATCH_FOR_INSERT	32768
+
+/** In the case of BTR_MODIFY_TREE, the caller specifies the intention
+to delete record only. It is used to optimize block->lock range.*/
+#define BTR_LATCH_FOR_DELETE	65536
+
 #define BTR_LATCH_MODE_WITHOUT_FLAGS(latch_mode)	\
 	((latch_mode) & ~(BTR_INSERT			\
 			  | BTR_DELETE_MARK		\
 			  | BTR_DELETE			\
 			  | BTR_ESTIMATE		\
 			  | BTR_IGNORE_SEC_UNIQUE	\
-			  | BTR_ALREADY_S_LATCHED))
+			  | BTR_ALREADY_S_LATCHED	\
+			  | BTR_LATCH_FOR_INSERT	\
+			  | BTR_LATCH_FOR_DELETE))
+
+#define BTR_LATCH_MODE_WITHOUT_INTENTION(latch_mode)	\
+	((latch_mode) & ~(BTR_LATCH_FOR_INSERT		\
+			  | BTR_LATCH_FOR_DELETE))
 #endif /* UNIV_HOTBACKUP */
 
 /**************************************************************//**
@@ -214,8 +232,8 @@ btr_blob_dbg_owner(
 #endif /* UNIV_BLOB_DEBUG */
 
 /**************************************************************//**
-Gets the root node of a tree and x-latches it.
- at return	root page, x-latched */
+Gets the root node of a tree and sx-latches it for segment access.
+ at return root page, sx-latched */
 UNIV_INTERN
 page_t*
 btr_root_get(
@@ -797,13 +815,14 @@ btr_index_rec_validate(
 	__attribute__((nonnull, warn_unused_result));
 /**************************************************************//**
 Checks the consistency of an index tree.
- at return	TRUE if ok */
+ at return true if ok */
 UNIV_INTERN
 bool
 btr_validate_index(
 /*===============*/
-	dict_index_t*	index,			/*!< in: index */
-	const trx_t*	trx)			/*!< in: transaction or 0 */
+	dict_index_t*	index,	/*!< in: index */
+	const trx_t*	trx,	/*!< in: transaction or 0 */
+	bool		lockout)/*!< in: true if X-latch index is intended */
 	__attribute__((nonnull(1), warn_unused_result));
 
 #ifdef UNIV_SYNC_DEBUG
diff --git a/storage/innobase/include/btr0btr.ic b/storage/innobase/include/btr0btr.ic
index 40b468b..0a9c9eb 100644
--- a/storage/innobase/include/btr0btr.ic
+++ b/storage/innobase/include/btr0btr.ic
@@ -164,8 +164,10 @@ btr_page_get_next(
 {
 	ut_ad(page && mtr);
 #ifndef UNIV_INNOCHECKSUM
-	ut_ad(mtr_memo_contains_page(mtr, page, MTR_MEMO_PAGE_X_FIX)
-	      || mtr_memo_contains_page(mtr, page, MTR_MEMO_PAGE_S_FIX));
+	ut_ad(mtr_memo_contains_page_flagged(mtr, page,
+					     MTR_MEMO_PAGE_S_FIX
+					     | MTR_MEMO_PAGE_X_FIX
+					     | MTR_MEMO_PAGE_SX_FIX));
 #endif /* UNIV_INNOCHECKSUM */
 	return(mach_read_from_4(page + FIL_PAGE_NEXT));
 }
diff --git a/storage/innobase/include/btr0pcur.ic b/storage/innobase/include/btr0pcur.ic
index 7e355d3..f3f3a9d 100644
--- a/storage/innobase/include/btr0pcur.ic
+++ b/storage/innobase/include/btr0pcur.ic
@@ -473,7 +473,7 @@ btr_pcur_open_with_no_init_func(
 {
 	btr_cur_t*	btr_cursor;
 
-	cursor->latch_mode = latch_mode;
+	cursor->latch_mode = BTR_LATCH_MODE_WITHOUT_INTENTION(latch_mode);
 	cursor->search_mode = mode;
 
 	/* Search with the tree cursor */
diff --git a/storage/innobase/include/btr0types.h b/storage/innobase/include/btr0types.h
index c1a4531..df67b14 100644
--- a/storage/innobase/include/btr0types.h
+++ b/storage/innobase/include/btr0types.h
@@ -195,6 +195,10 @@ The reference is stored at the end of the prefix of the field
 in the index record. */
 #define BTR_EXTERN_FIELD_REF_SIZE	20
 
+/** If the data don't exceed the size, the data are stored locally. */
+#define BTR_EXTERN_LOCAL_STORED_MAX_SIZE	\
+	(BTR_EXTERN_FIELD_REF_SIZE * 2)
+
 /** A BLOB field reference full of zero, for use in assertions and tests.
 Initially, BLOB field references are set to zero, in
 dtuple_convert_big_rec(). */
diff --git a/storage/innobase/include/buf0buf.ic b/storage/innobase/include/buf0buf.ic
index 842aa67..ae56599 100644
--- a/storage/innobase/include/buf0buf.ic
+++ b/storage/innobase/include/buf0buf.ic
@@ -980,7 +980,8 @@ buf_block_modify_clock_inc(
 
 	ut_ad((buf_pool_mutex_own(buf_pool)
 	       && (block->page.buf_fix_count == 0))
-	      || rw_lock_own(&(block->lock), RW_LOCK_EXCLUSIVE));
+	      || rw_lock_own_flagged(&block->lock,
+				     RW_LOCK_FLAG_X | RW_LOCK_FLAG_SX));
 #endif /* UNIV_SYNC_DEBUG */
 
 	block->modify_clock++;
@@ -1388,9 +1389,11 @@ buf_page_release(
 	rw_lock_s_unlock(&(block->debug_latch));
 #endif
 	if (rw_latch == RW_S_LATCH) {
-		rw_lock_s_unlock(&(block->lock));
+		rw_lock_s_unlock(&block->lock);
+	} else if (rw_latch == RW_SX_LATCH) {
+		rw_lock_sx_unlock(&block->lock);
 	} else if (rw_latch == RW_X_LATCH) {
-		rw_lock_x_unlock(&(block->lock));
+		rw_lock_x_unlock(&block->lock);
 	}
 
 	buf_block_unfix(block);
diff --git a/storage/innobase/include/buf0flu.ic b/storage/innobase/include/buf0flu.ic
index a763cd1..d715025 100644
--- a/storage/innobase/include/buf0flu.ic
+++ b/storage/innobase/include/buf0flu.ic
@@ -66,7 +66,8 @@ buf_flush_note_modification(
 	ut_ad(buf_block_get_state(block) == BUF_BLOCK_FILE_PAGE);
 	ut_ad(block->page.buf_fix_count > 0);
 #ifdef UNIV_SYNC_DEBUG
-	ut_ad(rw_lock_own(&(block->lock), RW_LOCK_EX));
+	ut_ad(rw_lock_own_flagged(&block->lock,
+				  RW_LOCK_FLAG_X | RW_LOCK_FLAG_SX));
 #endif /* UNIV_SYNC_DEBUG */
 
 	ut_ad(!buf_pool_mutex_own(buf_pool));
diff --git a/storage/innobase/include/dict0dict.h b/storage/innobase/include/dict0dict.h
index 326b9e7..7f76740 100644
--- a/storage/innobase/include/dict0dict.h
+++ b/storage/innobase/include/dict0dict.h
@@ -1866,17 +1866,15 @@ const char*
 dict_tf_to_row_format_string(
 /*=========================*/
 	ulint	table_flag);		/*!< in: row format setting */
-/*****************************************************************//**
-Get index by first field of the index
- at return index which is having first field matches
-with the field present in field_index position of table */
-UNIV_INLINE
-dict_index_t*
-dict_table_get_index_on_first_col(
-/*==============================*/
-	const dict_table_t*	table,		/*!< in: table */
-	ulint			col_index);	/*!< in: position of column
-						in table */
+/****************************************************************//**
+Return maximum size of the node pointer record.
+ at return maximum size of the record in bytes */
+
+ulint
+dict_index_node_ptr_max_size(
+/*=========================*/
+	const dict_index_t*	index)	/*!< in: index */
+	__attribute__((warn_unused_result, pure));
 
 #endif /* !UNIV_HOTBACKUP */
 
diff --git a/storage/innobase/include/fut0fut.ic b/storage/innobase/include/fut0fut.ic
index b065b10..4e43552 100644
--- a/storage/innobase/include/fut0fut.ic
+++ b/storage/innobase/include/fut0fut.ic
@@ -45,7 +45,9 @@ fut_get_ptr(
 	byte*		ptr;
 
 	ut_ad(addr.boffset < UNIV_PAGE_SIZE);
-	ut_ad((rw_latch == RW_S_LATCH) || (rw_latch == RW_X_LATCH));
+	ut_ad((rw_latch == RW_S_LATCH)
+	      || (rw_latch == RW_X_LATCH)
+	      || (rw_latch == RW_SX_LATCH));
 
 	block = buf_page_get(space, zip_size, addr.page, rw_latch, mtr);
 	ptr = buf_block_get_frame(block) + addr.boffset;
diff --git a/storage/innobase/include/fut0lst.ic b/storage/innobase/include/fut0lst.ic
index d18cf21..c7e24bc 100644
--- a/storage/innobase/include/fut0lst.ic
+++ b/storage/innobase/include/fut0lst.ic
@@ -54,7 +54,9 @@ flst_write_addr(
 	mtr_t*		mtr)	/*!< in: mini-transaction handle */
 {
 	ut_ad(faddr && mtr);
-	ut_ad(mtr_memo_contains_page(mtr, faddr, MTR_MEMO_PAGE_X_FIX));
+	ut_ad(mtr_memo_contains_page_flagged(mtr, faddr,
+					     MTR_MEMO_PAGE_X_FIX
+					     | MTR_MEMO_PAGE_SX_FIX));
 	ut_a(addr.page == FIL_NULL || addr.boffset >= FIL_PAGE_DATA);
 	ut_a(ut_align_offset(faddr, UNIV_PAGE_SIZE) >= FIL_PAGE_DATA);
 
@@ -94,7 +96,9 @@ flst_init(
 	flst_base_node_t*	base,	/*!< in: pointer to base node */
 	mtr_t*			mtr)	/*!< in: mini-transaction handle */
 {
-	ut_ad(mtr_memo_contains_page(mtr, base, MTR_MEMO_PAGE_X_FIX));
+	ut_ad(mtr_memo_contains_page_flagged(mtr, base,
+					     MTR_MEMO_PAGE_X_FIX
+					     | MTR_MEMO_PAGE_SX_FIX));
 
 	mlog_write_ulint(base + FLST_LEN, 0, MLOG_4BYTES, mtr);
 	flst_write_addr(base + FLST_FIRST, fil_addr_null, mtr);
diff --git a/storage/innobase/include/mtr0mtr.h b/storage/innobase/include/mtr0mtr.h
index 3e196d1..41c51c7 100644
--- a/storage/innobase/include/mtr0mtr.h
+++ b/storage/innobase/include/mtr0mtr.h
@@ -269,19 +269,27 @@ mtr_release_block_at_savepoint(
 	ulint		savepoint,	/*!< in: savepoint */
 	buf_block_t*	block);		/*!< in: block to release */
 /**********************************************************//**
-Relax the block latch in an mtr memo after a savepoint
-from X to SX. */
+X-latches the not yet latched block after a savepoint. */
 
 void
-mtr_block_x_to_sx_at_savepoint(
+mtr_block_x_latch_at_savepoint(
 /*===========================*/
 	mtr_t*		mtr,		/*!< in: mtr */
 	ulint		savepoint,	/*!< in: savepoint */
-	buf_block_t*	block);		/*!< in: block to relax latch */
+	buf_block_t*	block);		/*!< in: block to X latch */
+/**********************************************************//**
+SX-latches the not yet latched block after a savepoint. */
+
+void
+mtr_block_sx_latch_at_savepoint(
+/*============================*/
+	mtr_t*		mtr,		/*!< in: mtr */
+	ulint		savepoint,	/*!< in: savepoint */
+	buf_block_t*	block);		/*!< in: block to SX latch */
 #else /* !UNIV_HOTBACKUP */
 # define mtr_release_s_latch_at_savepoint(mtr,savepoint,lock) ((void) 0)
 # define mtr_release_block_at_savepoint(mtr,savepoint,lock) ((void) 0)
-# define mtr_block_x_to_sx_at_savepoint(mtr,savepoint,lock) ((void) 0)
+# define mtr_block_latch_at_savepoint(mtr,savepoint,lock,type) ((void) 0)
 #endif /* !UNIV_HOTBACKUP */
 
 /**********************************************************//**
diff --git a/storage/innobase/include/page0page.h b/storage/innobase/include/page0page.h
index 2b47aef..5872e11 100644
--- a/storage/innobase/include/page0page.h
+++ b/storage/innobase/include/page0page.h
@@ -675,6 +675,51 @@ page_rec_is_infimum(
 /*================*/
 	const rec_t*	rec)	/*!< in: record */
 	__attribute__((const));
+
+/************************************************************//**
+true if the record is the first user record on a page.
+ at return true if the first user record */
+UNIV_INLINE
+bool
+page_rec_is_first(
+/*==============*/
+	const rec_t*	rec,	/*!< in: record */
+	const page_t*	page)	/*!< in: page */
+	__attribute__((const));
+
+/************************************************************//**
+true if the record is the second user record on a page.
+ at return true if the second user record */
+UNIV_INLINE
+bool
+page_rec_is_second(
+/*===============*/
+	const rec_t*	rec,	/*!< in: record */
+	const page_t*	page)	/*!< in: page */
+	__attribute__((const));
+
+/************************************************************//**
+true if the record is the last user record on a page.
+ at return true if the last user record */
+UNIV_INLINE
+bool
+page_rec_is_last(
+/*=============*/
+	const rec_t*	rec,	/*!< in: record */
+	const page_t*	page)	/*!< in: page */
+	__attribute__((const));
+
+/************************************************************//**
+true if the record is the second last user record on a page.
+ at return true if the second last user record */
+UNIV_INLINE
+bool
+page_rec_is_second_last(
+/*====================*/
+	const rec_t*	rec,	/*!< in: record */
+	const page_t*	page)	/*!< in: page */
+	__attribute__((const));
+
 /***************************************************************//**
 Looks for the record which owns the given record.
 @return	the owner record */
diff --git a/storage/innobase/include/page0page.ic b/storage/innobase/include/page0page.ic
index cde3cad..e1b29cb 100644
--- a/storage/innobase/include/page0page.ic
+++ b/storage/innobase/include/page0page.ic
@@ -458,6 +458,69 @@ page_rec_is_infimum(
 }
 
 /************************************************************//**
+true if the record is the first user record on a page.
+ at return true if the first user record */
+UNIV_INLINE
+bool
+page_rec_is_first(
+/*==============*/
+	const rec_t*	rec,	/*!< in: record */
+	const page_t*	page)	/*!< in: page */
+{
+	ut_ad(page_get_n_recs(page) > 0);
+
+	return(page_rec_get_next_const(page_get_infimum_rec(page)) == rec);
+}
+
+/************************************************************//**
+true if the record is the second user record on a page.
+ at return true if the second user record */
+UNIV_INLINE
+bool
+page_rec_is_second(
+/*===============*/
+	const rec_t*	rec,	/*!< in: record */
+	const page_t*	page)	/*!< in: page */
+{
+	ut_ad(page_get_n_recs(page) > 1);
+
+	return(page_rec_get_next_const(
+		page_rec_get_next_const(page_get_infimum_rec(page))) == rec);
+}
+
+/************************************************************//**
+true if the record is the last user record on a page.
+ at return true if the last user record */
+UNIV_INLINE
+bool
+page_rec_is_last(
+/*=============*/
+	const rec_t*	rec,	/*!< in: record */
+	const page_t*	page)	/*!< in: page */
+{
+	ut_ad(page_get_n_recs(page) > 0);
+
+	return(page_rec_get_next_const(rec) == page_get_supremum_rec(page));
+}
+
+/************************************************************//**
+true if the record is the second last user record on a page.
+ at return true if the second last user record */
+UNIV_INLINE
+bool
+page_rec_is_second_last(
+/*====================*/
+	const rec_t*	rec,	/*!< in: record */
+	const page_t*	page)	/*!< in: page */
+{
+	ut_ad(page_get_n_recs(page) > 1);
+	ut_ad(!page_rec_is_last(rec, page));
+
+	return(page_rec_get_next_const(
+		page_rec_get_next_const(rec)) == page_get_supremum_rec(page));
+}
+
+/************************************************************//**
 Returns the nth record of the record list.
 This is the inverse function of page_rec_get_n_recs_before().
 @return	nth record */
diff --git a/storage/innobase/include/row0log.ic b/storage/innobase/include/row0log.ic
index b0f37db..f968c9b 100644
--- a/storage/innobase/include/row0log.ic
+++ b/storage/innobase/include/row0log.ic
@@ -57,8 +57,10 @@ row_log_online_op_try(
 				or 0 for delete */
 {
 #ifdef UNIV_SYNC_DEBUG
-	ut_ad(rw_lock_own(dict_index_get_lock(index), RW_LOCK_SHARED)
-	      || rw_lock_own(dict_index_get_lock(index), RW_LOCK_EX));
+	ut_ad(rw_lock_own_flagged(dict_index_get_lock(index),
+				  RW_LOCK_FLAG_S
+				  | RW_LOCK_FLAG_X
+				  | RW_LOCK_FLAG_SX));
 #endif /* UNIV_SYNC_DEBUG */
 
 	switch (dict_index_get_online_status(index)) {
diff --git a/storage/innobase/include/sync0rw.h b/storage/innobase/include/sync0rw.h
index a4259df..184bd63 100644
--- a/storage/innobase/include/sync0rw.h
+++ b/storage/innobase/include/sync0rw.h
@@ -105,10 +105,12 @@ struct rw_lock_stats_t {
 numerical values smaller than 30 (smaller than BTR_MODIFY_TREE and
 MTR_MEMO_MODIFY) and the order of the numerical values like below! and they
 should be 2pow value to be used also as ORed combination of flag. */
-#define RW_S_LATCH	1
-#define	RW_X_LATCH	2
-#define	RW_SX_LATCH	4
-#define	RW_NO_LATCH	8
+enum rw_lock_type_t {
+	RW_S_LATCH = 1,
+	RW_X_LATCH = 2,
+	RW_SX_LATCH = 4,
+	RW_NO_LATCH = 8
+};
 
 #ifndef UNIV_HOTBACKUP
 /* We decrement lock_word by X_LOCK_DECR for each x_lock. It is also the
@@ -310,6 +312,8 @@ unlocking, not the corresponding function. */
 	rw_lock_sx_lock_func((M), (P), (F), (L))
 #define rw_lock_sx_lock_gen(M, P)				\
 	rw_lock_sx_lock_func((M), (P), __FILE__, __LINE__)
+#define rw_lock_sx_lock_nowait(M, P)				\
+	rw_lock_sx_lock_low((M), (P), __FILE__, __LINE__)
 #ifdef UNIV_SYNC_DEBUG
 # define rw_lock_sx_unlock(L)		rw_lock_sx_unlock_func(0, L)
 # define rw_lock_sx_unlock_gen(L, P)	rw_lock_sx_unlock_func(P, L)
@@ -429,6 +433,18 @@ rw_lock_x_lock_func(
 	const char*	file_name,/*!< in: file name where lock requested */
 	ulint		line);	/*!< in: line where requested */
 /******************************************************************//**
+Low-level function for acquiring an sx lock.
+ at return FALSE if did not succeed, TRUE if success. */
+UNIV_INTERN
+ibool
+rw_lock_sx_lock_low(
+/*================*/
+	rw_lock_t*	lock,	/*!< in: pointer to rw-lock */
+	ulint		pass,	/*!< in: pass value; != 0, if the lock will
+				be passed to another thread to unlock */
+	const char*	file_name,/*!< in: file name where lock requested */
+	ulint		line);	/*!< in: line where requested */
+/******************************************************************//**
 NOTE! Use the corresponding macro, not directly this function! Lock an
 rw-lock in SX mode for the current thread. If the rw-lock is locked
 in exclusive mode, or there is an exclusive lock request waiting,
@@ -437,7 +453,7 @@ for the lock, before suspending the thread. If the same thread has an x-lock
 on the rw-lock, locking succeed, with the following exception: if pass != 0,
 only a single sx-lock may be taken on the lock. NOTE: If the same thread has
 an s-lock, locking does not succeed! */
-
+UNIV_INTERN
 void
 rw_lock_sx_lock_func(
 /*=================*/
diff --git a/storage/innobase/mtr/mtr0mtr.cc b/storage/innobase/mtr/mtr0mtr.cc
index ef6fe09..e91a9da 100644
--- a/storage/innobase/mtr/mtr0mtr.cc
+++ b/storage/innobase/mtr/mtr0mtr.cc
@@ -182,7 +182,6 @@ mtr_memo_note_modifications(
 	ut_ad(mtr->magic_n == MTR_MAGIC_N);
 	ut_ad(mtr->state == MTR_COMMITTING); /* Currently only used in
 					     commit */
-
 	for (const dyn_block_t* block = dyn_array_get_last_block(&mtr->memo);
 	     block;
 	     block = dyn_array_get_prev_block(&mtr->memo, block)) {
@@ -367,7 +366,7 @@ mtr_memo_release(
 	ut_ad(mtr->state == MTR_ACTIVE);
 	/* We cannot release a page that has been written to in the
 	middle of a mini-transaction. */
-	ut_ad(!mtr->modifications || type != MTR_MEMO_PAGE_X_FIX);
+	ut_ad(!mtr->modifications || !(type & MTR_MEMO_PAGE_X_FIX));
 
 	for (const dyn_block_t* block = dyn_array_get_last_block(&mtr->memo);
 	     block;
@@ -383,7 +382,7 @@ mtr_memo_release(
 		ut_ad(!(dyn_block_get_used(block) % sizeof(mtr_memo_slot_t)));
 
 		while (slot-- != start) {
-			if (object == slot->object && type == slot->type) {
+			if (object == slot->object && (type & slot->type)) {
 				mtr_memo_slot_release(mtr, slot);
 				return(true);
 			}
@@ -421,16 +420,16 @@ mtr_release_block_at_savepoint(
 
 	slot->object = NULL;
 }
+
 /**********************************************************//**
-Relax the block latch in an mtr memo after a savepoint
-from X to SX. */
+X-latches the not yet latched block after a savepoint. */
 
 void
-mtr_block_x_to_sx_at_savepoint(
+mtr_block_x_latch_at_savepoint(
 /*===========================*/
 	mtr_t*		mtr,		/*!< in: mtr */
 	ulint		savepoint,	/*!< in: savepoint */
-	buf_block_t*	block)		/*!< in: block to relax latch */
+	buf_block_t*	block)		/*!< in: block to X latch */
 {
 	mtr_memo_slot_t* slot;
 	dyn_array_t*	memo;
@@ -438,6 +437,10 @@ mtr_block_x_to_sx_at_savepoint(
 	ut_ad(mtr);
 	ut_ad(mtr->magic_n == MTR_MAGIC_N);
 	ut_ad(mtr->state == MTR_ACTIVE);
+	ut_ad(!mtr_memo_contains_flagged(mtr, block,
+					 MTR_MEMO_PAGE_S_FIX
+					 | MTR_MEMO_PAGE_X_FIX
+					 | MTR_MEMO_PAGE_SX_FIX));
 
 	memo = &mtr->memo;
 
@@ -445,10 +448,54 @@ mtr_block_x_to_sx_at_savepoint(
 		dyn_array_get_element(memo, savepoint));
 
 	ut_a(slot->object == block);
-	ut_a(slot->type == MTR_MEMO_PAGE_X_FIX);
+	ut_a(slot->type == MTR_MEMO_BUF_FIX); /* == RW_NO_LATCH */
+
+	rw_lock_x_lock(&block->lock);
+
+	if (!mtr->made_dirty) {
+		mtr->made_dirty =
+			mtr_block_dirtied(block);
+	}
+
+	slot->type = MTR_MEMO_PAGE_X_FIX;
+}
+
+/**********************************************************//**
+SX-latches the not yet latched block after a savepoint. */
+
+void
+mtr_block_sx_latch_at_savepoint(
+/*============================*/
+	mtr_t*		mtr,		/*!< in: mtr */
+	ulint		savepoint,	/*!< in: savepoint */
+	buf_block_t*	block)		/*!< in: block to SX latch */
+{
+	mtr_memo_slot_t* slot;
+	dyn_array_t*	memo;
+
+	ut_ad(mtr);
+	ut_ad(mtr->magic_n == MTR_MAGIC_N);
+	ut_ad(mtr->state == MTR_ACTIVE);
+	ut_ad(!mtr_memo_contains_flagged(mtr, block,
+					 MTR_MEMO_PAGE_S_FIX
+					 | MTR_MEMO_PAGE_X_FIX
+					 | MTR_MEMO_PAGE_SX_FIX));
+
+	memo = &mtr->memo;
+
+	slot = static_cast<mtr_memo_slot_t*>(
+		dyn_array_get_element(memo, savepoint));
+
+	ut_a(slot->object == block);
+	ut_a(slot->type == MTR_MEMO_BUF_FIX); /* == RW_NO_LATCH */
 
 	rw_lock_sx_lock(&block->lock);
-	rw_lock_x_unlock(&block->lock);
+
+	if (!mtr->made_dirty) {
+		mtr->made_dirty =
+			mtr_block_dirtied(block);
+	}
+
 	slot->type = MTR_MEMO_PAGE_SX_FIX;
 }
 #endif /* !UNIV_HOTBACKUP */
@@ -493,7 +540,7 @@ mtr_memo_contains_page(
 /**********************************************************//**
 Checks if memo contains the given page.
 @return true if contains */
-
+UNIV_INTERN
 bool
 mtr_memo_contains_page_flagged(
 /*===========================*/
diff --git a/storage/innobase/rem/rem0cmp.cc b/storage/innobase/rem/rem0cmp.cc
index 426cf9e..deb0b294 100644
--- a/storage/innobase/rem/rem0cmp.cc
+++ b/storage/innobase/rem/rem0cmp.cc
@@ -844,11 +844,7 @@ cmp_dtuple_rec_with_match_low(
 			up to the common fields */
 order_resolved:
 	ut_ad((ret >= - 1) && (ret <= 1));
-	ut_ad(ret == cmp_debug_dtuple_rec_with_match(dtuple, rec, offsets,
-						     n_cmp, matched_fields));
-	ut_ad(*matched_fields == cur_field); /* In the debug version, the
-					     above cmp_debug_... sets
-					     *matched_fields to a value */
+
 	*matched_fields = cur_field;
 	*matched_bytes = cur_bytes;
 
diff --git a/storage/innobase/row/row0import.cc b/storage/innobase/row/row0import.cc
index d5f766e..8563bf7 100644
--- a/storage/innobase/row/row0import.cc
+++ b/storage/innobase/row/row0import.cc
@@ -1615,7 +1615,8 @@ IndexPurge::purge_pessimistic_delete() UNIV_NOTHROW
 {
 	dberr_t	err;
 
-	btr_pcur_restore_position(BTR_MODIFY_TREE, &m_pcur, &m_mtr);
+	btr_pcur_restore_position(BTR_MODIFY_TREE | BTR_LATCH_FOR_DELETE,
+				  &m_pcur, &m_mtr);
 
 	ut_ad(rec_get_deleted_flag(
 			btr_pcur_get_rec(&m_pcur),
diff --git a/storage/innobase/row/row0ins.cc b/storage/innobase/row/row0ins.cc
index 44c9ac3..08246b9 100644
--- a/storage/innobase/row/row0ins.cc
+++ b/storage/innobase/row/row0ins.cc
@@ -2505,6 +2505,8 @@ row_ins_clust_index_entry_low(
 				goto err_exit;
 			}
 
+			DEBUG_SYNC_C("before_insert_pessimitic_row_ins_clust");
+
 			err = btr_cur_optimistic_insert(
 				flags, &cursor,
 				&offsets, &offsets_heap,
@@ -2581,7 +2583,7 @@ row_ins_sec_mtr_start_trx_and_check_if_aborted(
 	if (search_mode & BTR_ALREADY_S_LATCHED) {
 		mtr_s_lock(dict_index_get_lock(index), mtr);
 	} else {
-		mtr_x_lock(dict_index_get_lock(index), mtr);
+		mtr_sx_lock(dict_index_get_lock(index), mtr);
 	}
 
 	switch (index->online_status) {
@@ -2652,7 +2654,7 @@ row_ins_sec_index_entry_low(
 			search_mode |= BTR_ALREADY_S_LATCHED;
 			mtr_s_lock(dict_index_get_lock(index), &mtr);
 		} else {
-			mtr_x_lock(dict_index_get_lock(index), &mtr);
+			mtr_sx_lock(dict_index_get_lock(index), &mtr);
 		}
 
 		if (row_log_online_op_try(
diff --git a/storage/innobase/row/row0log.cc b/storage/innobase/row/row0log.cc
index caed087..e66aeed 100644
--- a/storage/innobase/row/row0log.cc
+++ b/storage/innobase/row/row0log.cc
@@ -517,8 +517,10 @@ row_log_table_delete(
 	ut_ad(rec_offs_n_fields(offsets) == dict_index_get_n_fields(index));
 	ut_ad(rec_offs_size(offsets) <= sizeof index->online_log->tail.buf);
 #ifdef UNIV_SYNC_DEBUG
-	ut_ad(rw_lock_own(&index->lock, RW_LOCK_SHARED)
-	      || rw_lock_own(&index->lock, RW_LOCK_EX));
+	ut_ad(rw_lock_own_flagged(&index->lock,
+				  RW_LOCK_FLAG_S
+				  | RW_LOCK_FLAG_X
+				  | RW_LOCK_FLAG_SX));
 #endif /* UNIV_SYNC_DEBUG */
 
 	if (dict_index_is_corrupted(index)
@@ -818,8 +820,10 @@ row_log_table_low(
 	ut_ad(rec_offs_n_fields(offsets) == dict_index_get_n_fields(index));
 	ut_ad(rec_offs_size(offsets) <= sizeof index->online_log->tail.buf);
 #ifdef UNIV_SYNC_DEBUG
-	ut_ad(rw_lock_own(&index->lock, RW_LOCK_SHARED)
-	      || rw_lock_own(&index->lock, RW_LOCK_EX));
+	ut_ad(rw_lock_own_flagged(&index->lock,
+				  RW_LOCK_FLAG_S
+				  | RW_LOCK_FLAG_X
+				  | RW_LOCK_FLAG_SX));
 #endif /* UNIV_SYNC_DEBUG */
 	ut_ad(fil_page_get_type(page_align(rec)) == FIL_PAGE_INDEX);
 	ut_ad(page_is_leaf(page_align(rec)));
@@ -1026,8 +1030,10 @@ row_log_table_get_pk(
 	ut_ad(dict_index_is_online_ddl(index));
 	ut_ad(!offsets || rec_offs_validate(rec, index, offsets));
 #ifdef UNIV_SYNC_DEBUG
-	ut_ad(rw_lock_own(&index->lock, RW_LOCK_SHARED)
-	      || rw_lock_own(&index->lock, RW_LOCK_EX));
+	ut_ad(rw_lock_own_flagged(&index->lock,
+				  RW_LOCK_FLAG_S
+				  | RW_LOCK_FLAG_X
+				  | RW_LOCK_FLAG_SX));
 #endif /* UNIV_SYNC_DEBUG */
 
 	ut_ad(log);
@@ -1222,7 +1228,8 @@ row_log_table_blob_free(
 	ut_ad(dict_index_is_clust(index));
 	ut_ad(dict_index_is_online_ddl(index));
 #ifdef UNIV_SYNC_DEBUG
-	ut_ad(rw_lock_own(&index->lock, RW_LOCK_EX));
+	ut_ad(rw_lock_own_flagged(&index->lock,
+				  RW_LOCK_FLAG_X | RW_LOCK_FLAG_SX));
 #endif /* UNIV_SYNC_DEBUG */
 	ut_ad(page_no != FIL_NULL);
 
@@ -1267,7 +1274,8 @@ row_log_table_blob_alloc(
 	ut_ad(dict_index_is_clust(index));
 	ut_ad(dict_index_is_online_ddl(index));
 #ifdef UNIV_SYNC_DEBUG
-	ut_ad(rw_lock_own(&index->lock, RW_LOCK_EX));
+	ut_ad(rw_lock_own_flagged(&index->lock,
+				  RW_LOCK_FLAG_X | RW_LOCK_FLAG_SX));
 #endif /* UNIV_SYNC_DEBUG */
 	ut_ad(page_no != FIL_NULL);
 
@@ -1606,7 +1614,8 @@ row_log_table_apply_delete_low(
 			row, save_ext, index, heap);
 		mtr_start(mtr);
 		btr_pcur_open(index, entry, PAGE_CUR_LE,
-			      BTR_MODIFY_TREE, pcur, mtr);
+			      BTR_MODIFY_TREE | BTR_LATCH_FOR_DELETE,
+			      pcur, mtr);
 #ifdef UNIV_DEBUG
 		switch (btr_pcur_get_btr_cur(pcur)->flag) {
 		case BTR_CUR_DELETE_REF:
@@ -1689,7 +1698,8 @@ row_log_table_apply_delete(
 
 	mtr_start(&mtr);
 	btr_pcur_open(index, old_pk, PAGE_CUR_LE,
-		      BTR_MODIFY_TREE, &pcur, &mtr);
+		      BTR_MODIFY_TREE | BTR_LATCH_FOR_DELETE,
+		      &pcur, &mtr);
 #ifdef UNIV_DEBUG
 	switch (btr_pcur_get_btr_cur(&pcur)->flag) {
 	case BTR_CUR_DELETE_REF:
diff --git a/storage/innobase/row/row0merge.cc b/storage/innobase/row/row0merge.cc
index 97746aa..fbf8a86 100644
--- a/storage/innobase/row/row0merge.cc
+++ b/storage/innobase/row/row0merge.cc
@@ -2486,7 +2486,8 @@ row_merge_insert_index_tuples(
 				mtr_commit(&mtr);
 				mtr_start(&mtr);
 				btr_cur_open_at_index_side(
-					false, index, BTR_MODIFY_TREE,
+					false, index,
+					BTR_MODIFY_TREE | BTR_LATCH_FOR_INSERT,
 					&cursor, 0, &mtr);
 				page_cur_position(
 					page_rec_get_prev(btr_cur_get_rec(
diff --git a/storage/innobase/row/row0purge.cc b/storage/innobase/row/row0purge.cc
index 8212a7b..64d9360 100644
--- a/storage/innobase/row/row0purge.cc
+++ b/storage/innobase/row/row0purge.cc
@@ -161,7 +161,7 @@ row_purge_remove_clust_if_poss_low(
 			btr_pcur_get_btr_cur(&node->pcur), 0, &mtr);
 	} else {
 		dberr_t	err;
-		ut_ad(mode == BTR_MODIFY_TREE);
+		ut_ad(mode == (BTR_MODIFY_TREE | BTR_LATCH_FOR_DELETE));
 		btr_cur_pessimistic_delete(
 			&err, FALSE, btr_pcur_get_btr_cur(&node->pcur), 0,
 			RB_NONE, &mtr);
@@ -207,7 +207,7 @@ row_purge_remove_clust_if_poss(
 	     n_tries < BTR_CUR_RETRY_DELETE_N_TIMES;
 	     n_tries++) {
 		if (row_purge_remove_clust_if_poss_low(
-			    node, BTR_MODIFY_TREE)) {
+			    node, BTR_MODIFY_TREE | BTR_LATCH_FOR_DELETE)) {
 			return(true);
 		}
 
@@ -283,7 +283,7 @@ row_purge_remove_sec_if_poss_tree(
 		index->name starts with TEMP_INDEX_PREFIX (meaning
 		that the index is or was being created online). It is
 		protected by index->lock. */
-		mtr_x_lock(dict_index_get_lock(index), &mtr);
+		mtr_sx_lock(dict_index_get_lock(index), &mtr);
 
 		if (dict_index_is_online_ddl(index)) {
 			/* Online secondary index creation will not
@@ -300,8 +300,10 @@ row_purge_remove_sec_if_poss_tree(
 		ut_ad(!dict_index_is_online_ddl(index));
 	}
 
-	search_result = row_search_index_entry(index, entry, BTR_MODIFY_TREE,
-					       &pcur, &mtr);
+	search_result = row_search_index_entry(
+				index, entry,
+				BTR_MODIFY_TREE | BTR_LATCH_FOR_DELETE,
+				&pcur, &mtr);
 
 	switch (search_result) {
 	case ROW_NOT_FOUND:
@@ -663,11 +665,11 @@ row_purge_upd_exist_or_extern_func(
 
 			mtr_start(&mtr);
 
-			/* We have to acquire an X-latch to the clustered
-			index tree */
+			/* We have to acquire an SX-latch to the clustered
+			index tree (exclude other tree changes) */
 
 			index = dict_table_get_first_index(node->table);
-			mtr_x_lock(dict_index_get_lock(index), &mtr);
+			mtr_sx_lock(dict_index_get_lock(index), &mtr);
 
 			/* NOTE: we must also acquire an X-latch to the
 			root page of the tree. We will need it when we
diff --git a/storage/innobase/row/row0uins.cc b/storage/innobase/row/row0uins.cc
index 849bf09..137ea94 100644
--- a/storage/innobase/row/row0uins.cc
+++ b/storage/innobase/row/row0uins.cc
@@ -141,8 +141,9 @@ row_undo_ins_remove_clust_rec(
 	/* If did not succeed, try pessimistic descent to tree */
 	mtr_start(&mtr);
 
-	success = btr_pcur_restore_position(BTR_MODIFY_TREE,
-					    &(node->pcur), &mtr);
+	success = btr_pcur_restore_position(
+			BTR_MODIFY_TREE | BTR_LATCH_FOR_DELETE,
+			&node->pcur, &mtr);
 	ut_a(success);
 
 	btr_cur_pessimistic_delete(&err, FALSE, btr_cur, 0,
@@ -200,8 +201,8 @@ row_undo_ins_remove_sec_low(
 		mode = BTR_MODIFY_LEAF | BTR_ALREADY_S_LATCHED;
 		mtr_s_lock(dict_index_get_lock(index), &mtr);
 	} else {
-		ut_ad(mode == BTR_MODIFY_TREE);
-		mtr_x_lock(dict_index_get_lock(index), &mtr);
+		ut_ad(mode == (BTR_MODIFY_TREE | BTR_LATCH_FOR_DELETE));
+		mtr_sx_lock(dict_index_get_lock(index), &mtr);
 	}
 
 	if (row_log_online_op_try(index, entry, 0)) {
@@ -226,7 +227,7 @@ row_undo_ins_remove_sec_low(
 
 	btr_cur = btr_pcur_get_btr_cur(&pcur);
 
-	if (mode != BTR_MODIFY_TREE) {
+	if (mode != (BTR_MODIFY_TREE | BTR_LATCH_FOR_DELETE)) {
 		err = btr_cur_optimistic_delete(btr_cur, 0, &mtr)
 			? DB_SUCCESS : DB_FAIL;
 	} else {
@@ -272,7 +273,9 @@ row_undo_ins_remove_sec(
 
 	/* Try then pessimistic descent to the B-tree */
 retry:
-	err = row_undo_ins_remove_sec_low(BTR_MODIFY_TREE, index, entry);
+	err = row_undo_ins_remove_sec_low(
+		BTR_MODIFY_TREE | BTR_LATCH_FOR_DELETE,
+		index, entry);
 
 	/* The delete operation may fail if we have little
 	file space left: TODO: easiest to crash the database
diff --git a/storage/innobase/row/row0umod.cc b/storage/innobase/row/row0umod.cc
index 7649add..9dc0eab 100644
--- a/storage/innobase/row/row0umod.cc
+++ b/storage/innobase/row/row0umod.cc
@@ -251,7 +251,7 @@ row_undo_mod_remove_clust_low(
 			? DB_SUCCESS
 			: DB_FAIL;
 	} else {
-		ut_ad(mode == BTR_MODIFY_TREE);
+		ut_ad(mode == (BTR_MODIFY_TREE | BTR_LATCH_FOR_DELETE));
 
 		/* This operation is analogous to purge, we can free also
 		inherited externally stored fields */
@@ -341,8 +341,10 @@ row_undo_mod_clust(
 
 	if (err == DB_SUCCESS && online) {
 #ifdef UNIV_SYNC_DEBUG
-		ut_ad(rw_lock_own(&index->lock, RW_LOCK_SHARED)
-		      || rw_lock_own(&index->lock, RW_LOCK_EX));
+		ut_ad(rw_lock_own_flagged(&index->lock,
+					  RW_LOCK_FLAG_S
+					  | RW_LOCK_FLAG_X
+					  | RW_LOCK_FLAG_SX));
 #endif /* UNIV_SYNC_DEBUG */
 		switch (node->rec_type) {
 		case TRX_UNDO_DEL_MARK_REC:
@@ -393,8 +395,9 @@ row_undo_mod_clust(
 
 			mtr_start_trx(&mtr, thr_get_trx(thr));
 
-			err = row_undo_mod_remove_clust_low(node, thr, &mtr,
-							    BTR_MODIFY_TREE);
+			err = row_undo_mod_remove_clust_low(
+				node, thr, &mtr,
+				BTR_MODIFY_TREE | BTR_LATCH_FOR_DELETE);
 
 			ut_ad(err == DB_SUCCESS
 			      || err == DB_OUT_OF_FILE_SPACE);
@@ -449,8 +452,8 @@ row_undo_mod_del_mark_or_remove_sec_low(
 			mode = BTR_MODIFY_LEAF | BTR_ALREADY_S_LATCHED;
 			mtr_s_lock(dict_index_get_lock(index), &mtr);
 		} else {
-			ut_ad(mode == BTR_MODIFY_TREE);
-			mtr_x_lock(dict_index_get_lock(index), &mtr);
+			ut_ad(mode == (BTR_MODIFY_TREE | BTR_LATCH_FOR_DELETE));
+			mtr_sx_lock(dict_index_get_lock(index), &mtr);
 		}
 
 		if (row_log_online_op_try(index, entry, 0)) {
@@ -510,7 +513,7 @@ row_undo_mod_del_mark_or_remove_sec_low(
 	} else {
 		/* Remove the index record */
 
-		if (mode != BTR_MODIFY_TREE) {
+		if (BTR_LATCH_MODE_WITHOUT_INTENTION(mode) != BTR_MODIFY_TREE) {
 			success = btr_cur_optimistic_delete(btr_cur, 0, &mtr);
 			if (success) {
 				err = DB_SUCCESS;
@@ -572,7 +575,7 @@ row_undo_mod_del_mark_or_remove_sec(
 	}
 
 	err = row_undo_mod_del_mark_or_remove_sec_low(node, thr, index,
-						      entry, BTR_MODIFY_TREE);
+		entry, BTR_MODIFY_TREE | BTR_LATCH_FOR_DELETE);
 	return(err);
 }
 
@@ -622,7 +625,7 @@ row_undo_mod_del_unmark_sec_and_undo_update(
 			mtr_s_lock(dict_index_get_lock(index), &mtr);
 		} else {
 			ut_ad(mode == BTR_MODIFY_TREE);
-			mtr_x_lock(dict_index_get_lock(index), &mtr);
+			mtr_sx_lock(dict_index_get_lock(index), &mtr);
 		}
 
 		if (row_log_online_op_try(index, entry, trx->id)) {
diff --git a/storage/innobase/sync/sync0rw.cc b/storage/innobase/sync/sync0rw.cc
index 651375b..01285d6 100644
--- a/storage/innobase/sync/sync0rw.cc
+++ b/storage/innobase/sync/sync0rw.cc
@@ -450,6 +450,8 @@ rw_lock_s_lock_spin(
 		lock->count_os_wait++;
 		rw_lock_stats.rw_s_os_wait_count.add(counter_index, 1);
 
+		DEBUG_SYNC_C("rw_s_lock_waiting");
+
 		sync_array_wait_event(sync_arr, index);
 
 		i = 0;
@@ -575,7 +577,7 @@ rw_lock_x_lock_wait_func(
 /******************************************************************//**
 Low-level function for acquiring an exclusive lock.
 @return	FALSE if did not succeed, TRUE if success. */
-UNIV_INLINE
+UNIV_INTERN
 ibool
 rw_lock_x_lock_low(
 /*===============*/
@@ -663,7 +665,7 @@ rw_lock_x_lock_low(
 /******************************************************************//**
 Low-level function for acquiring an sx lock.
 @return FALSE if did not succeed, TRUE if success. */
-UNIV_INLINE
+UNIV_INTERN
 ibool
 rw_lock_sx_lock_low(
 /*================*/
@@ -673,6 +675,8 @@ rw_lock_sx_lock_low(
 	const char*	file_name,/*!< in: file name where lock requested */
 	ulint		line)	/*!< in: line where requested */
 {
+	ibool local_recursive= lock->recursive;
+
 	if (rw_lock_lock_word_decr(lock, X_LOCK_HALF_DECR, X_LOCK_HALF_DECR)) {
 
 		/* lock->recursive also tells us if the writer_thread
@@ -692,8 +696,13 @@ rw_lock_sx_lock_low(
 
 		/* Decrement failed: It already has an X or SX lock by this
 		thread or another thread. If it is this thread, relock,
-		else fail. */
-		if (!pass && lock->recursive
+		else fail.
+		Note: recursive must be loaded before writer_thread see
+		comment for rw_lock_set_writer_id_and_recursion_flag().
+		To achieve this we load it before rw_lock_lock_word_decr(),
+		which implies full memory barrier in current implementation. */
+
+		if (!pass && local_recursive
 		    && os_thread_eq(lock->writer_thread, thread_id)) {
 			/* This thread owns an X or SX lock */
 			if (lock->sx_recursive++ == 0) {
@@ -731,6 +740,13 @@ rw_lock_sx_lock_low(
 #ifdef UNIV_SYNC_DEBUG
 	rw_lock_add_debug_info(lock, pass, RW_LOCK_SX, file_name, line);
 #endif /* UNIV_SYNC_DEBUG */
+
+	if (srv_instrument_semaphores) {
+		lock->thread_id = os_thread_get_curr_id();
+		lock->file_name = file_name;
+		lock->line = line;
+	}
+
 	lock->last_x_file_name = file_name;
 	lock->last_x_line = (unsigned int) line;
 
@@ -890,6 +906,8 @@ rw_lock_sx_lock_func(
 		}
 
 		/* Spin waiting for the lock_word to become free */
+		os_rmb;
+		HMT_low();
 		while (i < SYNC_SPIN_ROUNDS
 		       && lock->lock_word <= X_LOCK_HALF_DECR) {
 			if (srv_spin_wait_delay) {
@@ -898,7 +916,9 @@ rw_lock_sx_lock_func(
 			}
 
 			i++;
+			os_rmb;
 		}
+		HMT_medium();
 		if (i == SYNC_SPIN_ROUNDS) {
 			os_thread_yield();
 		} else {
@@ -908,10 +928,8 @@ rw_lock_sx_lock_func(
 
 	rw_lock_stats.rw_sx_spin_round_count.add(counter_index, i);
 
-	sync_arr = sync_array_get();
-
-	sync_array_reserve_cell(
-		sync_arr, lock, RW_LOCK_SX, file_name, line, &index);
+	sync_arr = sync_array_get_and_reserve_cell(lock, RW_LOCK_EX,
+						   file_name, line, &index);
 
 	/* Waiters must be set before checking lock_word, to ensure signal
 	is sent. This could lead to a few unnecessary wake-up signals. */


More information about the commits mailing list