wl2723 - ndb opt. nr

mysql-test/t/rpl_multi_engine.test:
  merge fix
libmysqld/sql_tablespace.cc:
  New BitKeeper file ``libmysqld/sql_tablespace.cc''
mysql-test/r/ndb_basic_disk.result:
  New BitKeeper file ``mysql-test/r/ndb_basic_disk.result''
mysql-test/t/ndb_basic_disk.test:
  New BitKeeper file ``mysql-test/t/ndb_basic_disk.test''
sql/sql_tablespace.cc:
  New BitKeeper file ``sql/sql_tablespace.cc''
storage/ndb/src/kernel/blocks/OptNR.txt:
  New BitKeeper file ``storage/ndb/src/kernel/blocks/OptNR.txt''
storage/ndb/src/kernel/vm/mem.txt:
  New BitKeeper file ``storage/ndb/src/kernel/vm/mem.txt''
storage/ndb/src/kernel/vm/ndbd_malloc_impl.cpp:
  New BitKeeper file ``storage/ndb/src/kernel/vm/ndbd_malloc_impl.cpp''
storage/ndb/src/kernel/vm/ndbd_malloc_impl.hpp:
  New BitKeeper file ``storage/ndb/src/kernel/vm/ndbd_malloc_impl.hpp''
storage/ndb/tools/ndb_error_reporter:
  New BitKeeper file ``storage/ndb/tools/ndb_error_reporter''
This commit is contained in:
unknown 2006-01-11 11:35:25 +01:00
parent 2c0f53d69c
commit 641ce5e97e
138 changed files with 9336 additions and 3311 deletions

View File

@ -65,7 +65,8 @@ sqlsources = derror.cc field.cc field_conv.cc strfunc.cc filesort.cc \
sp_head.cc sp_pcontext.cc sp.cc sp_cache.cc sp_rcontext.cc \ sp_head.cc sp_pcontext.cc sp.cc sp_cache.cc sp_rcontext.cc \
parse_file.cc sql_view.cc sql_trigger.cc my_decimal.cc \ parse_file.cc sql_view.cc sql_trigger.cc my_decimal.cc \
item_xmlfunc.cc \ item_xmlfunc.cc \
rpl_filter.cc sql_partition.cc handlerton.cc sql_plugin.cc rpl_filter.cc sql_partition.cc handlerton.cc sql_plugin.cc \
sql_tablespace.cc
libmysqld_int_a_SOURCES= $(libmysqld_sources) $(libmysqlsources) $(sqlsources) libmysqld_int_a_SOURCES= $(libmysqld_sources) $(libmysqlsources) $(sqlsources)
EXTRA_libmysqld_a_SOURCES = ha_innodb.cc ha_berkeley.cc ha_archive.cc \ EXTRA_libmysqld_a_SOURCES = ha_innodb.cc ha_berkeley.cc ha_archive.cc \

View File

@ -0,0 +1,397 @@
DROP TABLE IF EXISTS t1;
CREATE LOGFILE GROUP lg1
ADD UNDOFILE 'undofile.dat'
INITIAL_SIZE 16M
UNDO_BUFFER_SIZE = 1M
ENGINE=NDB;
alter logfile group lg1
add undofile 'undofile02.dat'
initial_size 4M engine=ndb;
CREATE TABLESPACE ts1
ADD DATAFILE 'datafile.dat'
USE LOGFILE GROUP lg1
INITIAL_SIZE 12M
ENGINE NDB;
alter tablespace ts1
add datafile 'datafile02.dat'
initial_size 4M engine=ndb;
CREATE TABLE t1
(pk1 int not null primary key, b int not null, c int not null)
tablespace ts1 storage disk
engine ndb;
INSERT INTO t1 VALUES (0, 0, 0);
SELECT * FROM t1;
pk1 b c
0 0 0
INSERT INTO t1 VALUES
(1,1,1),(2,2,2),(3,3,3),(4,4,4),(5,5,5),
(6,6,6),(7,7,7),(8,8,8),(9,9,9),(10,10,10),
(11,11,11),(12,12,12),(13,13,13),(14,14,14),(15,15,15),
(16,16,16),(17,17,17),(18,18,18),(19,19,19),(20,20,20),
(21,21,21),(22,22,22),(23,23,23),(24,24,24),(25,25,25),
(26,26,26),(27,27,27),(28,28,28),(29,29,29),(30,30,30),
(31,31,31),(32,32,32),(33,33,33),(34,34,34),(35,35,35),
(36,36,36),(37,37,37),(38,38,38),(39,39,39),(40,40,40),
(41,41,41),(42,42,42),(43,43,43),(44,44,44),(45,45,45),
(46,46,46),(47,47,47),(48,48,48),(49,49,49),(50,50,50),
(51,51,51),(52,52,52),(53,53,53),(54,54,54),(55,55,55),
(56,56,56),(57,57,57),(58,58,58),(59,59,59),(60,60,60),
(61,61,61),(62,62,62),(63,63,63),(64,64,64),(65,65,65),
(66,66,66),(67,67,67),(68,68,68),(69,69,69),(70,70,70),
(71,71,71),(72,72,72),(73,73,73),(74,74,74),(75,75,75),
(76,76,76),(77,77,77),(78,78,78),(79,79,79),(80,80,80),
(81,81,81),(82,82,82),(83,83,83),(84,84,84),(85,85,85),
(86,86,86),(87,87,87),(88,88,88),(89,89,89),(90,90,90),
(91,91,91),(92,92,92),(93,93,93),(94,94,94),(95,95,95),
(96,96,96),(97,97,97),(98,98,98),(99,99,99),(100,100,100),
(101,101,101),(102,102,102),(103,103,103),(104,104,104),(105,105,105),
(106,106,106),(107,107,107),(108,108,108),(109,109,109),(110,110,110),
(111,111,111),(112,112,112),(113,113,113),(114,114,114),(115,115,115),
(116,116,116),(117,117,117),(118,118,118),(119,119,119),(120,120,120),
(121,121,121),(122,122,122),(123,123,123),(124,124,124),(125,125,125),
(126,126,126),(127,127,127),(128,128,128),(129,129,129),(130,130,130),
(131,131,131),(132,132,132),(133,133,133),(134,134,134),(135,135,135),
(136,136,136),(137,137,137),(138,138,138),(139,139,139),(140,140,140),
(141,141,141),(142,142,142),(143,143,143),(144,144,144),(145,145,145),
(146,146,146),(147,147,147),(148,148,148),(149,149,149),(150,150,150),
(151,151,151),(152,152,152),(153,153,153),(154,154,154),(155,155,155),
(156,156,156),(157,157,157),(158,158,158),(159,159,159),(160,160,160),
(161,161,161),(162,162,162),(163,163,163),(164,164,164),(165,165,165),
(166,166,166),(167,167,167),(168,168,168),(169,169,169),(170,170,170),
(171,171,171),(172,172,172),(173,173,173),(174,174,174),(175,175,175),
(176,176,176),(177,177,177),(178,178,178),(179,179,179),(180,180,180),
(181,181,181),(182,182,182),(183,183,183),(184,184,184),(185,185,185),
(186,186,186),(187,187,187),(188,188,188),(189,189,189),(190,190,190),
(191,191,191),(192,192,192),(193,193,193),(194,194,194),(195,195,195),
(196,196,196),(197,197,197),(198,198,198),(199,199,199),(200,200,200),
(201,201,201),(202,202,202),(203,203,203),(204,204,204),(205,205,205),
(206,206,206),(207,207,207),(208,208,208),(209,209,209),(210,210,210),
(211,211,211),(212,212,212),(213,213,213),(214,214,214),(215,215,215),
(216,216,216),(217,217,217),(218,218,218),(219,219,219),(220,220,220),
(221,221,221),(222,222,222),(223,223,223),(224,224,224),(225,225,225),
(226,226,226),(227,227,227),(228,228,228),(229,229,229),(230,230,230),
(231,231,231),(232,232,232),(233,233,233),(234,234,234),(235,235,235),
(236,236,236),(237,237,237),(238,238,238),(239,239,239),(240,240,240),
(241,241,241),(242,242,242),(243,243,243),(244,244,244),(245,245,245),
(246,246,246),(247,247,247),(248,248,248),(249,249,249),(250,250,250),
(251,251,251),(252,252,252),(253,253,253),(254,254,254),(255,255,255),
(256,256,256),(257,257,257),(258,258,258),(259,259,259),(260,260,260),
(261,261,261),(262,262,262),(263,263,263),(264,264,264),(265,265,265),
(266,266,266),(267,267,267),(268,268,268),(269,269,269),(270,270,270),
(271,271,271),(272,272,272),(273,273,273),(274,274,274),(275,275,275),
(276,276,276),(277,277,277),(278,278,278),(279,279,279),(280,280,280),
(281,281,281),(282,282,282),(283,283,283),(284,284,284),(285,285,285),
(286,286,286),(287,287,287),(288,288,288),(289,289,289),(290,290,290),
(291,291,291),(292,292,292),(293,293,293),(294,294,294),(295,295,295),
(296,296,296),(297,297,297),(298,298,298),(299,299,299),(300,300,300),
(301,301,301),(302,302,302),(303,303,303),(304,304,304),(305,305,305),
(306,306,306),(307,307,307),(308,308,308),(309,309,309),(310,310,310),
(311,311,311),(312,312,312),(313,313,313),(314,314,314),(315,315,315),
(316,316,316),(317,317,317),(318,318,318),(319,319,319),(320,320,320),
(321,321,321),(322,322,322),(323,323,323),(324,324,324),(325,325,325),
(326,326,326),(327,327,327),(328,328,328),(329,329,329),(330,330,330),
(331,331,331),(332,332,332),(333,333,333),(334,334,334),(335,335,335),
(336,336,336),(337,337,337),(338,338,338),(339,339,339),(340,340,340),
(341,341,341),(342,342,342),(343,343,343),(344,344,344),(345,345,345),
(346,346,346),(347,347,347),(348,348,348),(349,349,349),(350,350,350),
(351,351,351),(352,352,352),(353,353,353),(354,354,354),(355,355,355),
(356,356,356),(357,357,357),(358,358,358),(359,359,359),(360,360,360),
(361,361,361),(362,362,362),(363,363,363),(364,364,364),(365,365,365),
(366,366,366),(367,367,367),(368,368,368),(369,369,369),(370,370,370),
(371,371,371),(372,372,372),(373,373,373),(374,374,374),(375,375,375),
(376,376,376),(377,377,377),(378,378,378),(379,379,379),(380,380,380),
(381,381,381),(382,382,382),(383,383,383),(384,384,384),(385,385,385),
(386,386,386),(387,387,387),(388,388,388),(389,389,389),(390,390,390),
(391,391,391),(392,392,392),(393,393,393),(394,394,394),(395,395,395),
(396,396,396),(397,397,397),(398,398,398),(399,399,399),(400,400,400),
(401,401,401),(402,402,402),(403,403,403),(404,404,404),(405,405,405),
(406,406,406),(407,407,407),(408,408,408),(409,409,409),(410,410,410),
(411,411,411),(412,412,412),(413,413,413),(414,414,414),(415,415,415),
(416,416,416),(417,417,417),(418,418,418),(419,419,419),(420,420,420),
(421,421,421),(422,422,422),(423,423,423),(424,424,424),(425,425,425),
(426,426,426),(427,427,427),(428,428,428),(429,429,429),(430,430,430),
(431,431,431),(432,432,432),(433,433,433),(434,434,434),(435,435,435),
(436,436,436),(437,437,437),(438,438,438),(439,439,439),(440,440,440),
(441,441,441),(442,442,442),(443,443,443),(444,444,444),(445,445,445),
(446,446,446),(447,447,447),(448,448,448),(449,449,449),(450,450,450),
(451,451,451),(452,452,452),(453,453,453),(454,454,454),(455,455,455),
(456,456,456),(457,457,457),(458,458,458),(459,459,459),(460,460,460),
(461,461,461),(462,462,462),(463,463,463),(464,464,464),(465,465,465),
(466,466,466),(467,467,467),(468,468,468),(469,469,469),(470,470,470),
(471,471,471),(472,472,472),(473,473,473),(474,474,474),(475,475,475),
(476,476,476),(477,477,477),(478,478,478),(479,479,479),(480,480,480),
(481,481,481),(482,482,482),(483,483,483),(484,484,484),(485,485,485),
(486,486,486),(487,487,487),(488,488,488),(489,489,489),(490,490,490),
(491,491,491),(492,492,492),(493,493,493),(494,494,494),(495,495,495),
(496,496,496),(497,497,497),(498,498,498),(499,499,499),(500, 500, 500);
SELECT COUNT(*) FROM t1;
COUNT(*)
501
CREATE LOGFILE GROUP lg2
ADD UNDOFILE 'x.dat'
INITIAL_SIZE 10y
engine = ndb;
ERROR HY000: A size parameter was incorrectly specified, either number or on the form 10M
CREATE LOGFILE GROUP lg2
ADD UNDOFILE 'x.dat'
INITIAL_SIZE 10MB
engine=ndb;
ERROR HY000: A size parameter was incorrectly specified, either number or on the form 10M
CREATE LOGFILE GROUP lg2
ADD UNDOFILE 'x.dat'
INITIAL_SIZE 10 MB
engine=ndb;
ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'MB
engine=ndb' at line 3
CREATE LOGFILE GROUP lg2
ADD UNDOFILE 'x.dat'
INITIAL_SIZE 10 M
engine=ndb;
ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'M
engine=ndb' at line 3
CREATE LOGFILE GROUP lg2
ADD UNDOFILE 'x.dat'
INITIAL_SIZE 1000000000000K
engine=ndb;
ERROR HY000: The size number was correct but we don't allow the digit part to be more than 2 billion
DROP TABLE t1;
create table t1 (a int primary key, b char(4) not null, c char(4) not null, key(b)) tablespace ts1 storage disk engine ndb;
insert into t1 values (1,'1','1'), (2,'2','2'), (3,'3','3');
begin;
update t1 set b = '2' where a = 1;
select b from t1 where a = 1;
b
2
select * from t1 where a = 1;
a b c
1 2 1
update t1 set c = '2' where a = 1;
select b from t1 where a = 1;
b
2
select * from t1 where a = 1;
a b c
1 2 2
update t1 set b = '3' where a = 1;
select b from t1 where a = 1;
b
3
select * from t1 where a = 1;
a b c
1 3 2
commit;
select * from t1 order by 1;
a b c
1 3 2
2 2 2
3 3 3
begin;
update t1 set c = '3' where a = 1;
select b from t1 where a = 1;
b
3
select * from t1 where a = 1;
a b c
1 3 3
update t1 set b = '4' where a = 1;
select b from t1 where a = 1;
b
4
select * from t1 where a = 1;
a b c
1 4 3
update t1 set c = '4' where a = 1;
select b from t1 where a = 1;
b
4
select * from t1 where a = 1;
a b c
1 4 4
commit;
select * from t1 order by 1;
a b c
1 4 4
2 2 2
3 3 3
update t1 set b = '5' where a = 1;
select * from t1 order by 1;
a b c
1 5 4
2 2 2
3 3 3
update t1 set b = '6' where b = '5';
select * from t1 order by 1;
a b c
1 6 4
2 2 2
3 3 3
update t1 set b = '7' where c = '4';
select * from t1 order by 1;
a b c
1 7 4
2 2 2
3 3 3
update t1 set c = '5' where a = 1;
select * from t1 order by 1;
a b c
1 7 5
2 2 2
3 3 3
update t1 set c = '6' where b = '7';
select * from t1 order by 1;
a b c
1 7 6
2 2 2
3 3 3
update t1 set c = '7' where c = '6';
select * from t1 order by 1;
a b c
1 7 7
2 2 2
3 3 3
drop table t1;
create table t1 (a int primary key, b varchar(4) not null, c char(4) not null, key(b)) tablespace ts1 storage disk engine ndb;
insert into t1 values (1,'1','1'), (2,'2','2'), (3,'3','3');
begin;
update t1 set b = '2' where a = 1;
select b from t1 where a = 1;
b
2
select * from t1 where a = 1;
a b c
1 2 1
update t1 set c = '2' where a = 1;
select b from t1 where a = 1;
b
2
select * from t1 where a = 1;
a b c
1 2 2
update t1 set b = '3' where a = 1;
select b from t1 where a = 1;
b
3
select * from t1 where a = 1;
a b c
1 3 2
commit;
select * from t1 order by 1;
a b c
1 3 2
2 2 2
3 3 3
begin;
update t1 set c = '3' where a = 1;
select b from t1 where a = 1;
b
3
select * from t1 where a = 1;
a b c
1 3 3
update t1 set b = '4' where a = 1;
select b from t1 where a = 1;
b
4
select * from t1 where a = 1;
a b c
1 4 3
update t1 set c = '4' where a = 1;
select b from t1 where a = 1;
b
4
select * from t1 where a = 1;
a b c
1 4 4
commit;
select * from t1 order by 1;
a b c
1 4 4
2 2 2
3 3 3
update t1 set b = '5' where a = 1;
select * from t1 order by 1;
a b c
1 5 4
2 2 2
3 3 3
update t1 set b = '6' where b = '5';
select * from t1 order by 1;
a b c
1 6 4
2 2 2
3 3 3
update t1 set b = '7' where c = '4';
select * from t1 order by 1;
a b c
1 7 4
2 2 2
3 3 3
update t1 set c = '5' where a = 1;
select * from t1 order by 1;
a b c
1 7 5
2 2 2
3 3 3
update t1 set c = '6' where b = '7';
select * from t1 order by 1;
a b c
1 7 6
2 2 2
3 3 3
update t1 set c = '7' where c = '6';
select * from t1 order by 1;
a b c
1 7 7
2 2 2
3 3 3
drop table t1;
create table t1 (
a int not null primary key,
b text not null
) tablespace ts1 storage disk engine=ndbcluster;
set @x0 = '01234567012345670123456701234567';
set @x0 = concat(@x0,@x0,@x0,@x0,@x0,@x0,@x0,@x0);
set @b1 = 'b1';
set @b1 = concat(@b1,@b1,@b1,@b1,@b1,@b1,@b1,@b1,@b1,@b1);
set @b1 = concat(@b1,@b1,@b1,@b1,@b1,@b1,@b1,@b1,@b1,@b1);
set @b1 = concat(@b1,@b1,@b1,@b1,@b1,@b1,@b1,@b1,@b1,@b1);
set @b1 = concat(@b1,@x0);
set @b2 = 'b2';
set @b2 = concat(@b2,@b2,@b2,@b2,@b2,@b2,@b2,@b2,@b2,@b2);
set @b2 = concat(@b2,@b2,@b2,@b2,@b2,@b2,@b2,@b2,@b2,@b2);
set @b2 = concat(@b2,@b2,@b2,@b2,@b2,@b2,@b2,@b2,@b2,@b2);
set @b2 = concat(@b2,@b2,@b2,@b2,@b2,@b2,@b2,@b2,@b2,@b2);
insert into t1 values(1,@b1);
insert into t1 values(2,@b2);
select a,length(b),substr(b,1+2*900,2) from t1 where a=1;
a length(b) substr(b,1+2*900,2)
1 2256 b1
select a,length(b),substr(b,1+2*9000,2) from t1 where a=2;
a length(b) substr(b,1+2*9000,2)
2 20000 b2
update t1 set b=@b2 where a=1;
update t1 set b=@b1 where a=2;
select a,length(b),substr(b,1+2*9000,2) from t1 where a=1;
a length(b) substr(b,1+2*9000,2)
1 20000 b2
select a,length(b),substr(b,1+2*900,2) from t1 where a=2;
a length(b) substr(b,1+2*900,2)
2 2256 b1
update t1 set b=concat(b,b) where a=1;
update t1 set b=concat(b,b) where a=2;
select a,length(b),substr(b,1+4*9000,2) from t1 where a=1;
a length(b) substr(b,1+4*9000,2)
1 40000 b2
select a,length(b),substr(b,1+4*900,2) from t1 where a=2;
a length(b) substr(b,1+4*900,2)
2 4512 b1
delete from t1 where a=1;
delete from t1 where a=2;
select count(*) from t1;
count(*)
0
drop table t1;
alter tablespace ts1 drop datafile 'datafile.dat' engine = ndb;
alter tablespace ts1 drop datafile 'datafile02.dat' engine = ndb;
drop tablespace ts1 engine = ndb;
drop logfile group lg1 engine = ndb;

View File

@ -55,6 +55,8 @@ Temporary table: no
Number of attributes: 4 Number of attributes: 4
Number of primary keys: 3 Number of primary keys: 3
Length of frm data: # Length of frm data: #
Row Checksum: 1
Row GCI: 1
TableStatus: Retrieved TableStatus: Retrieved
-- Attributes -- -- Attributes --
a Int PRIMARY KEY AT=FIXED ST=MEMORY a Int PRIMARY KEY AT=FIXED ST=MEMORY

View File

@ -0,0 +1,312 @@
-- source include/have_ndb.inc
--disable_warnings
DROP TABLE IF EXISTS t1;
--enable_warnings
#
# Basic test of disk tables for NDB
#
#
# Start by creating a logfile group
#
CREATE LOGFILE GROUP lg1
ADD UNDOFILE 'undofile.dat'
INITIAL_SIZE 16M
UNDO_BUFFER_SIZE = 1M
ENGINE=NDB;
alter logfile group lg1
add undofile 'undofile02.dat'
initial_size 4M engine=ndb;
#
# Create a tablespace connected to the logfile group
#
CREATE TABLESPACE ts1
ADD DATAFILE 'datafile.dat'
USE LOGFILE GROUP lg1
INITIAL_SIZE 12M
ENGINE NDB;
alter tablespace ts1
add datafile 'datafile02.dat'
initial_size 4M engine=ndb;
#
# Create a table using this tablespace
#
CREATE TABLE t1
(pk1 int not null primary key, b int not null, c int not null)
tablespace ts1 storage disk
engine ndb;
INSERT INTO t1 VALUES (0, 0, 0);
SELECT * FROM t1;
INSERT INTO t1 VALUES
(1,1,1),(2,2,2),(3,3,3),(4,4,4),(5,5,5),
(6,6,6),(7,7,7),(8,8,8),(9,9,9),(10,10,10),
(11,11,11),(12,12,12),(13,13,13),(14,14,14),(15,15,15),
(16,16,16),(17,17,17),(18,18,18),(19,19,19),(20,20,20),
(21,21,21),(22,22,22),(23,23,23),(24,24,24),(25,25,25),
(26,26,26),(27,27,27),(28,28,28),(29,29,29),(30,30,30),
(31,31,31),(32,32,32),(33,33,33),(34,34,34),(35,35,35),
(36,36,36),(37,37,37),(38,38,38),(39,39,39),(40,40,40),
(41,41,41),(42,42,42),(43,43,43),(44,44,44),(45,45,45),
(46,46,46),(47,47,47),(48,48,48),(49,49,49),(50,50,50),
(51,51,51),(52,52,52),(53,53,53),(54,54,54),(55,55,55),
(56,56,56),(57,57,57),(58,58,58),(59,59,59),(60,60,60),
(61,61,61),(62,62,62),(63,63,63),(64,64,64),(65,65,65),
(66,66,66),(67,67,67),(68,68,68),(69,69,69),(70,70,70),
(71,71,71),(72,72,72),(73,73,73),(74,74,74),(75,75,75),
(76,76,76),(77,77,77),(78,78,78),(79,79,79),(80,80,80),
(81,81,81),(82,82,82),(83,83,83),(84,84,84),(85,85,85),
(86,86,86),(87,87,87),(88,88,88),(89,89,89),(90,90,90),
(91,91,91),(92,92,92),(93,93,93),(94,94,94),(95,95,95),
(96,96,96),(97,97,97),(98,98,98),(99,99,99),(100,100,100),
(101,101,101),(102,102,102),(103,103,103),(104,104,104),(105,105,105),
(106,106,106),(107,107,107),(108,108,108),(109,109,109),(110,110,110),
(111,111,111),(112,112,112),(113,113,113),(114,114,114),(115,115,115),
(116,116,116),(117,117,117),(118,118,118),(119,119,119),(120,120,120),
(121,121,121),(122,122,122),(123,123,123),(124,124,124),(125,125,125),
(126,126,126),(127,127,127),(128,128,128),(129,129,129),(130,130,130),
(131,131,131),(132,132,132),(133,133,133),(134,134,134),(135,135,135),
(136,136,136),(137,137,137),(138,138,138),(139,139,139),(140,140,140),
(141,141,141),(142,142,142),(143,143,143),(144,144,144),(145,145,145),
(146,146,146),(147,147,147),(148,148,148),(149,149,149),(150,150,150),
(151,151,151),(152,152,152),(153,153,153),(154,154,154),(155,155,155),
(156,156,156),(157,157,157),(158,158,158),(159,159,159),(160,160,160),
(161,161,161),(162,162,162),(163,163,163),(164,164,164),(165,165,165),
(166,166,166),(167,167,167),(168,168,168),(169,169,169),(170,170,170),
(171,171,171),(172,172,172),(173,173,173),(174,174,174),(175,175,175),
(176,176,176),(177,177,177),(178,178,178),(179,179,179),(180,180,180),
(181,181,181),(182,182,182),(183,183,183),(184,184,184),(185,185,185),
(186,186,186),(187,187,187),(188,188,188),(189,189,189),(190,190,190),
(191,191,191),(192,192,192),(193,193,193),(194,194,194),(195,195,195),
(196,196,196),(197,197,197),(198,198,198),(199,199,199),(200,200,200),
(201,201,201),(202,202,202),(203,203,203),(204,204,204),(205,205,205),
(206,206,206),(207,207,207),(208,208,208),(209,209,209),(210,210,210),
(211,211,211),(212,212,212),(213,213,213),(214,214,214),(215,215,215),
(216,216,216),(217,217,217),(218,218,218),(219,219,219),(220,220,220),
(221,221,221),(222,222,222),(223,223,223),(224,224,224),(225,225,225),
(226,226,226),(227,227,227),(228,228,228),(229,229,229),(230,230,230),
(231,231,231),(232,232,232),(233,233,233),(234,234,234),(235,235,235),
(236,236,236),(237,237,237),(238,238,238),(239,239,239),(240,240,240),
(241,241,241),(242,242,242),(243,243,243),(244,244,244),(245,245,245),
(246,246,246),(247,247,247),(248,248,248),(249,249,249),(250,250,250),
(251,251,251),(252,252,252),(253,253,253),(254,254,254),(255,255,255),
(256,256,256),(257,257,257),(258,258,258),(259,259,259),(260,260,260),
(261,261,261),(262,262,262),(263,263,263),(264,264,264),(265,265,265),
(266,266,266),(267,267,267),(268,268,268),(269,269,269),(270,270,270),
(271,271,271),(272,272,272),(273,273,273),(274,274,274),(275,275,275),
(276,276,276),(277,277,277),(278,278,278),(279,279,279),(280,280,280),
(281,281,281),(282,282,282),(283,283,283),(284,284,284),(285,285,285),
(286,286,286),(287,287,287),(288,288,288),(289,289,289),(290,290,290),
(291,291,291),(292,292,292),(293,293,293),(294,294,294),(295,295,295),
(296,296,296),(297,297,297),(298,298,298),(299,299,299),(300,300,300),
(301,301,301),(302,302,302),(303,303,303),(304,304,304),(305,305,305),
(306,306,306),(307,307,307),(308,308,308),(309,309,309),(310,310,310),
(311,311,311),(312,312,312),(313,313,313),(314,314,314),(315,315,315),
(316,316,316),(317,317,317),(318,318,318),(319,319,319),(320,320,320),
(321,321,321),(322,322,322),(323,323,323),(324,324,324),(325,325,325),
(326,326,326),(327,327,327),(328,328,328),(329,329,329),(330,330,330),
(331,331,331),(332,332,332),(333,333,333),(334,334,334),(335,335,335),
(336,336,336),(337,337,337),(338,338,338),(339,339,339),(340,340,340),
(341,341,341),(342,342,342),(343,343,343),(344,344,344),(345,345,345),
(346,346,346),(347,347,347),(348,348,348),(349,349,349),(350,350,350),
(351,351,351),(352,352,352),(353,353,353),(354,354,354),(355,355,355),
(356,356,356),(357,357,357),(358,358,358),(359,359,359),(360,360,360),
(361,361,361),(362,362,362),(363,363,363),(364,364,364),(365,365,365),
(366,366,366),(367,367,367),(368,368,368),(369,369,369),(370,370,370),
(371,371,371),(372,372,372),(373,373,373),(374,374,374),(375,375,375),
(376,376,376),(377,377,377),(378,378,378),(379,379,379),(380,380,380),
(381,381,381),(382,382,382),(383,383,383),(384,384,384),(385,385,385),
(386,386,386),(387,387,387),(388,388,388),(389,389,389),(390,390,390),
(391,391,391),(392,392,392),(393,393,393),(394,394,394),(395,395,395),
(396,396,396),(397,397,397),(398,398,398),(399,399,399),(400,400,400),
(401,401,401),(402,402,402),(403,403,403),(404,404,404),(405,405,405),
(406,406,406),(407,407,407),(408,408,408),(409,409,409),(410,410,410),
(411,411,411),(412,412,412),(413,413,413),(414,414,414),(415,415,415),
(416,416,416),(417,417,417),(418,418,418),(419,419,419),(420,420,420),
(421,421,421),(422,422,422),(423,423,423),(424,424,424),(425,425,425),
(426,426,426),(427,427,427),(428,428,428),(429,429,429),(430,430,430),
(431,431,431),(432,432,432),(433,433,433),(434,434,434),(435,435,435),
(436,436,436),(437,437,437),(438,438,438),(439,439,439),(440,440,440),
(441,441,441),(442,442,442),(443,443,443),(444,444,444),(445,445,445),
(446,446,446),(447,447,447),(448,448,448),(449,449,449),(450,450,450),
(451,451,451),(452,452,452),(453,453,453),(454,454,454),(455,455,455),
(456,456,456),(457,457,457),(458,458,458),(459,459,459),(460,460,460),
(461,461,461),(462,462,462),(463,463,463),(464,464,464),(465,465,465),
(466,466,466),(467,467,467),(468,468,468),(469,469,469),(470,470,470),
(471,471,471),(472,472,472),(473,473,473),(474,474,474),(475,475,475),
(476,476,476),(477,477,477),(478,478,478),(479,479,479),(480,480,480),
(481,481,481),(482,482,482),(483,483,483),(484,484,484),(485,485,485),
(486,486,486),(487,487,487),(488,488,488),(489,489,489),(490,490,490),
(491,491,491),(492,492,492),(493,493,493),(494,494,494),(495,495,495),
(496,496,496),(497,497,497),(498,498,498),(499,499,499),(500, 500, 500);
SELECT COUNT(*) FROM t1;
#
# Test error cases with size numbers
#
--error ER_WRONG_SIZE_NUMBER
CREATE LOGFILE GROUP lg2
ADD UNDOFILE 'x.dat'
INITIAL_SIZE 10y
engine = ndb;
--error ER_WRONG_SIZE_NUMBER
CREATE LOGFILE GROUP lg2
ADD UNDOFILE 'x.dat'
INITIAL_SIZE 10MB
engine=ndb;
--error 1064
CREATE LOGFILE GROUP lg2
ADD UNDOFILE 'x.dat'
INITIAL_SIZE 10 MB
engine=ndb;
--error 1064
CREATE LOGFILE GROUP lg2
ADD UNDOFILE 'x.dat'
INITIAL_SIZE 10 M
engine=ndb;
--error ER_SIZE_OVERFLOW_ERROR
CREATE LOGFILE GROUP lg2
ADD UNDOFILE 'x.dat'
INITIAL_SIZE 1000000000000K
engine=ndb;
DROP TABLE t1;
# Test update of mm/dd part
create table t1 (a int primary key, b char(4) not null, c char(4) not null, key(b)) tablespace ts1 storage disk engine ndb;
insert into t1 values (1,'1','1'), (2,'2','2'), (3,'3','3');
begin;
update t1 set b = '2' where a = 1;
select b from t1 where a = 1;
select * from t1 where a = 1;
update t1 set c = '2' where a = 1;
select b from t1 where a = 1;
select * from t1 where a = 1;
update t1 set b = '3' where a = 1;
select b from t1 where a = 1;
select * from t1 where a = 1;
commit;
select * from t1 order by 1;
begin;
update t1 set c = '3' where a = 1;
select b from t1 where a = 1;
select * from t1 where a = 1;
update t1 set b = '4' where a = 1;
select b from t1 where a = 1;
select * from t1 where a = 1;
update t1 set c = '4' where a = 1;
select b from t1 where a = 1;
select * from t1 where a = 1;
commit;
select * from t1 order by 1;
update t1 set b = '5' where a = 1;
select * from t1 order by 1;
update t1 set b = '6' where b = '5';
select * from t1 order by 1;
update t1 set b = '7' where c = '4';
select * from t1 order by 1;
update t1 set c = '5' where a = 1;
select * from t1 order by 1;
update t1 set c = '6' where b = '7';
select * from t1 order by 1;
update t1 set c = '7' where c = '6';
select * from t1 order by 1;
drop table t1;
create table t1 (a int primary key, b varchar(4) not null, c char(4) not null, key(b)) tablespace ts1 storage disk engine ndb;
insert into t1 values (1,'1','1'), (2,'2','2'), (3,'3','3');
begin;
update t1 set b = '2' where a = 1;
select b from t1 where a = 1;
select * from t1 where a = 1;
update t1 set c = '2' where a = 1;
select b from t1 where a = 1;
select * from t1 where a = 1;
update t1 set b = '3' where a = 1;
select b from t1 where a = 1;
select * from t1 where a = 1;
commit;
select * from t1 order by 1;
begin;
update t1 set c = '3' where a = 1;
select b from t1 where a = 1;
select * from t1 where a = 1;
update t1 set b = '4' where a = 1;
select b from t1 where a = 1;
select * from t1 where a = 1;
update t1 set c = '4' where a = 1;
select b from t1 where a = 1;
select * from t1 where a = 1;
commit;
select * from t1 order by 1;
update t1 set b = '5' where a = 1;
select * from t1 order by 1;
update t1 set b = '6' where b = '5';
select * from t1 order by 1;
update t1 set b = '7' where c = '4';
select * from t1 order by 1;
update t1 set c = '5' where a = 1;
select * from t1 order by 1;
update t1 set c = '6' where b = '7';
select * from t1 order by 1;
update t1 set c = '7' where c = '6';
select * from t1 order by 1;
drop table t1;
# Test for blobs...
create table t1 (
a int not null primary key,
b text not null
) tablespace ts1 storage disk engine=ndbcluster;
# b1 length 2000+256 (blob part aligned)
set @x0 = '01234567012345670123456701234567';
set @x0 = concat(@x0,@x0,@x0,@x0,@x0,@x0,@x0,@x0);
set @b1 = 'b1';
set @b1 = concat(@b1,@b1,@b1,@b1,@b1,@b1,@b1,@b1,@b1,@b1);
set @b1 = concat(@b1,@b1,@b1,@b1,@b1,@b1,@b1,@b1,@b1,@b1);
set @b1 = concat(@b1,@b1,@b1,@b1,@b1,@b1,@b1,@b1,@b1,@b1);
set @b1 = concat(@b1,@x0);
# b2 length 20000
set @b2 = 'b2';
set @b2 = concat(@b2,@b2,@b2,@b2,@b2,@b2,@b2,@b2,@b2,@b2);
set @b2 = concat(@b2,@b2,@b2,@b2,@b2,@b2,@b2,@b2,@b2,@b2);
set @b2 = concat(@b2,@b2,@b2,@b2,@b2,@b2,@b2,@b2,@b2,@b2);
set @b2 = concat(@b2,@b2,@b2,@b2,@b2,@b2,@b2,@b2,@b2,@b2);
insert into t1 values(1,@b1);
insert into t1 values(2,@b2);
select a,length(b),substr(b,1+2*900,2) from t1 where a=1;
select a,length(b),substr(b,1+2*9000,2) from t1 where a=2;
update t1 set b=@b2 where a=1;
update t1 set b=@b1 where a=2;
select a,length(b),substr(b,1+2*9000,2) from t1 where a=1;
select a,length(b),substr(b,1+2*900,2) from t1 where a=2;
update t1 set b=concat(b,b) where a=1;
update t1 set b=concat(b,b) where a=2;
select a,length(b),substr(b,1+4*9000,2) from t1 where a=1;
select a,length(b),substr(b,1+4*900,2) from t1 where a=2;
delete from t1 where a=1;
delete from t1 where a=2;
select count(*) from t1;
drop table t1;
alter tablespace ts1 drop datafile 'datafile.dat' engine = ndb;
alter tablespace ts1 drop datafile 'datafile02.dat' engine = ndb;
drop tablespace ts1 engine = ndb;
drop logfile group lg1 engine = ndb;

View File

@ -98,7 +98,7 @@ mysqld_SOURCES = sql_lex.cc sql_handler.cc sql_partition.cc \
sp_head.cc sp_pcontext.cc sp_rcontext.cc sp.cc \ sp_head.cc sp_pcontext.cc sp_rcontext.cc sp.cc \
sp_cache.cc parse_file.cc sql_trigger.cc \ sp_cache.cc parse_file.cc sql_trigger.cc \
sql_plugin.cc sql_binlog.cc \ sql_plugin.cc sql_binlog.cc \
handlerton.cc handlerton.cc sql_tablespace.cc
EXTRA_mysqld_SOURCES = ha_innodb.cc ha_berkeley.cc ha_archive.cc \ EXTRA_mysqld_SOURCES = ha_innodb.cc ha_berkeley.cc ha_archive.cc \
ha_innodb.h ha_berkeley.h ha_archive.h \ ha_innodb.h ha_berkeley.h ha_archive.h \
ha_blackhole.cc ha_federated.cc ha_ndbcluster.cc \ ha_blackhole.cc ha_federated.cc ha_ndbcluster.cc \

View File

@ -149,6 +149,7 @@ handlerton berkeley_hton = {
NULL, /* Start Consistent Snapshot */ NULL, /* Start Consistent Snapshot */
berkeley_flush_logs, /* Flush logs */ berkeley_flush_logs, /* Flush logs */
berkeley_show_status, /* Show status */ berkeley_show_status, /* Show status */
NULL, /* Alter Tablespace */
HTON_CLOSE_CURSORS_AT_COMMIT | HTON_FLUSH_AFTER_RENAME HTON_CLOSE_CURSORS_AT_COMMIT | HTON_FLUSH_AFTER_RENAME
}; };

View File

@ -57,6 +57,7 @@ handlerton blackhole_hton= {
NULL, /* Start Consistent Snapshot */ NULL, /* Start Consistent Snapshot */
NULL, /* Flush logs */ NULL, /* Flush logs */
NULL, /* Show status */ NULL, /* Show status */
NULL, /* Alter Tablespace */
HTON_CAN_RECREATE HTON_CAN_RECREATE
}; };

View File

@ -394,6 +394,7 @@ handlerton federated_hton= {
NULL, /* Start Consistent Snapshot */ NULL, /* Start Consistent Snapshot */
NULL, /* Flush logs */ NULL, /* Flush logs */
NULL, /* Show status */ NULL, /* Show status */
NULL, /* Alter Tablespace */
HTON_ALTER_NOT_SUPPORTED HTON_ALTER_NOT_SUPPORTED
}; };

View File

@ -54,6 +54,7 @@ handlerton heap_hton= {
NULL, /* Start Consistent Snapshot */ NULL, /* Start Consistent Snapshot */
NULL, /* Flush logs */ NULL, /* Flush logs */
NULL, /* Show status */ NULL, /* Show status */
NULL, /* Alter Tablespace */
HTON_CAN_RECREATE HTON_CAN_RECREATE
}; };

View File

@ -86,6 +86,7 @@ handlerton myisam_hton= {
NULL, /* Start Consistent Snapshot */ NULL, /* Start Consistent Snapshot */
NULL, /* Flush logs */ NULL, /* Flush logs */
NULL, /* Show status */ NULL, /* Show status */
NULL, /* Alter Tablespace */
HTON_CAN_RECREATE HTON_CAN_RECREATE
}; };

View File

@ -64,6 +64,7 @@ handlerton myisammrg_hton= {
NULL, /* Start Consistent Snapshot */ NULL, /* Start Consistent Snapshot */
NULL, /* Flush logs */ NULL, /* Flush logs */
NULL, /* Show status */ NULL, /* Show status */
NULL, /* Alter Tablespace */
HTON_CAN_RECREATE HTON_CAN_RECREATE
}; };

View File

@ -57,6 +57,7 @@ static int ndbcluster_close_connection(THD *thd);
static int ndbcluster_commit(THD *thd, bool all); static int ndbcluster_commit(THD *thd, bool all);
static int ndbcluster_rollback(THD *thd, bool all); static int ndbcluster_rollback(THD *thd, bool all);
static handler* ndbcluster_create_handler(TABLE_SHARE *table); static handler* ndbcluster_create_handler(TABLE_SHARE *table);
static int ndbcluster_alter_tablespace(THD* thd, st_alter_tablespace *info);
handlerton ndbcluster_hton = { handlerton ndbcluster_hton = {
MYSQL_HANDLERTON_INTERFACE_VERSION, MYSQL_HANDLERTON_INTERFACE_VERSION,
@ -86,6 +87,7 @@ handlerton ndbcluster_hton = {
NULL, /* Start Consistent Snapshot */ NULL, /* Start Consistent Snapshot */
NULL, /* Flush logs */ NULL, /* Flush logs */
ndbcluster_show_status, /* Show status */ ndbcluster_show_status, /* Show status */
ndbcluster_alter_tablespace,
HTON_NO_FLAGS HTON_NO_FLAGS
}; };
@ -4020,12 +4022,7 @@ int ha_ndbcluster::create(const char *name,
if ((my_errno= create_ndb_column(col, field, info))) if ((my_errno= create_ndb_column(col, field, info)))
DBUG_RETURN(my_errno); DBUG_RETURN(my_errno);
if ( if (info->store_on_disk || getenv("NDB_DEFAULT_DISK"))
#ifdef NDB_DISKDATA
info->store_on_disk ||
#else
getenv("NDB_DEFAULT_DISK"))
#endif
col.setStorageType(NdbDictionary::Column::StorageTypeDisk); col.setStorageType(NdbDictionary::Column::StorageTypeDisk);
else else
col.setStorageType(NdbDictionary::Column::StorageTypeMemory); col.setStorageType(NdbDictionary::Column::StorageTypeMemory);
@ -4045,14 +4042,11 @@ int ha_ndbcluster::create(const char *name,
NdbDictionary::Column::StorageTypeMemory); NdbDictionary::Column::StorageTypeMemory);
} }
#ifdef NDB_DISKDATA
if (info->store_on_disk) if (info->store_on_disk)
if (info->tablespace) if (info->tablespace)
tab.setTablespace(info->tablespace); tab.setTablespace(info->tablespace);
else else
tab.setTablespace("DEFAULT-TS"); tab.setTablespace("DEFAULT-TS");
#endif
// No primary key, create shadow key as 64 bit, auto increment // No primary key, create shadow key as 64 bit, auto increment
if (form->s->primary_key == MAX_KEY) if (form->s->primary_key == MAX_KEY)
{ {
@ -8315,7 +8309,6 @@ bool ha_ndbcluster::check_if_incompatible_data(HA_CREATE_INFO *info,
return COMPATIBLE_DATA_YES; return COMPATIBLE_DATA_YES;
} }
#ifdef NDB_DISKDATA
bool set_up_tablespace(st_alter_tablespace *info, bool set_up_tablespace(st_alter_tablespace *info,
NdbDictionary::Tablespace *ndb_ts) NdbDictionary::Tablespace *ndb_ts)
{ {
@ -8356,21 +8349,25 @@ bool set_up_undofile(st_alter_tablespace *info,
return false; return false;
} }
int ha_ndbcluster::alter_tablespace(st_alter_tablespace *info) int ndbcluster_alter_tablespace(THD* thd, st_alter_tablespace *info)
{ {
Ndb *ndb;
NDBDICT *dict;
int error;
DBUG_ENTER("ha_ndbcluster::alter_tablespace"); DBUG_ENTER("ha_ndbcluster::alter_tablespace");
if (check_ndb_connection())
Ndb *ndb= check_ndb_in_thd(thd);
if (ndb == NULL)
{ {
DBUG_RETURN(my_errno= HA_ERR_NO_CONNECTION); DBUG_RETURN(HA_ERR_NO_CONNECTION);
} }
ndb= get_ndb();
dict= ndb->getDictionary(); NDBDICT *dict = ndb->getDictionary();
int error;
const char * errmsg;
switch (info->ts_cmd_type){ switch (info->ts_cmd_type){
case (CREATE_TABLESPACE): case (CREATE_TABLESPACE):
{ {
error= ER_CREATE_TABLESPACE_FAILED;
NdbDictionary::Tablespace ndb_ts; NdbDictionary::Tablespace ndb_ts;
NdbDictionary::Datafile ndb_df; NdbDictionary::Datafile ndb_df;
if (set_up_tablespace(info, &ndb_ts)) if (set_up_tablespace(info, &ndb_ts))
@ -8381,23 +8378,24 @@ int ha_ndbcluster::alter_tablespace(st_alter_tablespace *info)
{ {
DBUG_RETURN(1); DBUG_RETURN(1);
} }
if (error= dict->createTablespace(ndb_ts)) errmsg= "TABLESPACE";
if (dict->createTablespace(ndb_ts))
{ {
DBUG_PRINT("error", ("createTablespace returned %d", error)); DBUG_PRINT("error", ("createTablespace returned %d", error));
my_error(ER_CREATE_TABLESPACE_FAILED, MYF(0), "TABLESPACE"); goto ndberror;
DBUG_RETURN(1);
} }
DBUG_PRINT("info", ("Successfully created Tablespace")); DBUG_PRINT("info", ("Successfully created Tablespace"));
if (error= dict->createDatafile(ndb_df)) errmsg= "DATAFILE";
if (dict->createDatafile(ndb_df))
{ {
DBUG_PRINT("error", ("createDatafile returned %d", error)); DBUG_PRINT("error", ("createDatafile returned %d", error));
my_error(ER_CREATE_TABLESPACE_FAILED, MYF(0), "DATAFILE"); goto ndberror;
DBUG_RETURN(1);
} }
break; break;
} }
case (ALTER_TABLESPACE): case (ALTER_TABLESPACE):
{ {
error= ER_ALTER_TABLESPACE_FAILED;
if (info->ts_alter_tablespace_type == ALTER_TABLESPACE_ADD_FILE) if (info->ts_alter_tablespace_type == ALTER_TABLESPACE_ADD_FILE)
{ {
NdbDictionary::Datafile ndb_df; NdbDictionary::Datafile ndb_df;
@ -8405,11 +8403,10 @@ int ha_ndbcluster::alter_tablespace(st_alter_tablespace *info)
{ {
DBUG_RETURN(1); DBUG_RETURN(1);
} }
if (error= dict->createDatafile(ndb_df)) errmsg= " CREATE DATAFILE";
if (dict->createDatafile(ndb_df))
{ {
DBUG_PRINT("error", ("createDatafile returned %d", error)); goto ndberror;
my_error(ER_ALTER_TABLESPACE_FAILED, MYF(0), "CREATE DATAFILE");
DBUG_RETURN(1);
} }
} }
else if(info->ts_alter_tablespace_type == ALTER_TABLESPACE_DROP_FILE) else if(info->ts_alter_tablespace_type == ALTER_TABLESPACE_DROP_FILE)
@ -8418,11 +8415,10 @@ int ha_ndbcluster::alter_tablespace(st_alter_tablespace *info)
info->data_file_name); info->data_file_name);
if (strcmp(df.getPath(), info->data_file_name) == 0) if (strcmp(df.getPath(), info->data_file_name) == 0)
{ {
if (error= dict->dropDatafile(df)) errmsg= " DROP DATAFILE";
if (dict->dropDatafile(df))
{ {
DBUG_PRINT("error", ("createDatafile returned %d", error)); goto ndberror;
my_error(ER_ALTER_TABLESPACE_FAILED, MYF(0), " DROP DATAFILE");
DBUG_RETURN(1);
} }
} }
else else
@ -8442,6 +8438,7 @@ int ha_ndbcluster::alter_tablespace(st_alter_tablespace *info)
} }
case (CREATE_LOGFILE_GROUP): case (CREATE_LOGFILE_GROUP):
{ {
error= ER_CREATE_TABLESPACE_FAILED;
NdbDictionary::LogfileGroup ndb_lg; NdbDictionary::LogfileGroup ndb_lg;
NdbDictionary::Undofile ndb_uf; NdbDictionary::Undofile ndb_uf;
if (info->undo_file_name == NULL) if (info->undo_file_name == NULL)
@ -8455,27 +8452,26 @@ int ha_ndbcluster::alter_tablespace(st_alter_tablespace *info)
{ {
DBUG_RETURN(1); DBUG_RETURN(1);
} }
if (error= dict->createLogfileGroup(ndb_lg)) errmsg= "LOGFILE GROUP";
if (dict->createLogfileGroup(ndb_lg))
{ {
DBUG_PRINT("error", ("createLogfileGroup returned %d", error)); goto ndberror;
my_error(ER_CREATE_TABLESPACE_FAILED, MYF(0), "LOGFILE GROUP");
DBUG_RETURN(1);
} }
DBUG_PRINT("info", ("Successfully created Logfile Group")); DBUG_PRINT("info", ("Successfully created Logfile Group"));
if (set_up_undofile(info, &ndb_uf)) if (set_up_undofile(info, &ndb_uf))
{ {
DBUG_RETURN(1); DBUG_RETURN(1);
} }
if (error= dict->createUndofile(ndb_uf)) errmsg= "UNDOFILE";
if (dict->createUndofile(ndb_uf))
{ {
DBUG_PRINT("error", ("createUndofile returned %d", error)); goto ndberror;
my_error(ER_CREATE_TABLESPACE_FAILED, MYF(0), "UNDOFILE");
DBUG_RETURN(1);
} }
break; break;
} }
case (ALTER_LOGFILE_GROUP): case (ALTER_LOGFILE_GROUP):
{ {
error= ER_ALTER_TABLESPACE_FAILED;
if (info->undo_file_name == NULL) if (info->undo_file_name == NULL)
{ {
/* /*
@ -8488,32 +8484,30 @@ int ha_ndbcluster::alter_tablespace(st_alter_tablespace *info)
{ {
DBUG_RETURN(1); DBUG_RETURN(1);
} }
if (error= dict->createUndofile(ndb_uf)) errmsg= "CREATE UNDOFILE";
if (dict->createUndofile(ndb_uf))
{ {
DBUG_PRINT("error", ("createUndofile returned %d", error)); goto ndberror;
my_error(ER_ALTER_TABLESPACE_FAILED, MYF(0), "CREATE UNDOFILE");
DBUG_RETURN(1);
} }
break; break;
} }
case (DROP_TABLESPACE): case (DROP_TABLESPACE):
{ {
if (error= dict->dropTablespace( error= ER_DROP_TABLESPACE_FAILED;
dict->getTablespace(info->tablespace_name))) errmsg= "TABLESPACE";
if (dict->dropTablespace(dict->getTablespace(info->tablespace_name)))
{ {
DBUG_PRINT("error", ("dropTablespace returned %d", error)); goto ndberror;
my_error(ER_DROP_TABLESPACE_FAILED, MYF(0), "TABLESPACE");
DBUG_RETURN(1);
} }
break; break;
} }
case (DROP_LOGFILE_GROUP): case (DROP_LOGFILE_GROUP):
{ {
if (error= dict->dropLogfileGroup(dict->getLogfileGroup(info->logfile_group_name))) error= ER_DROP_TABLESPACE_FAILED;
errmsg= "LOGFILE GROUP";
if (dict->dropLogfileGroup(dict->getLogfileGroup(info->logfile_group_name)))
{ {
DBUG_PRINT("error", ("dropLogfileGroup returned %d", error)); goto ndberror;
my_error(ER_DROP_TABLESPACE_FAILED, MYF(0), "LOGFILE GROUP");
DBUG_RETURN(1);
} }
break; break;
} }
@ -8531,6 +8525,13 @@ int ha_ndbcluster::alter_tablespace(st_alter_tablespace *info)
} }
} }
DBUG_RETURN(FALSE); DBUG_RETURN(FALSE);
ndberror:
const NdbError err= dict->getNdbError();
ERR_PRINT(err);
ndb_to_mysql_error(&err);
my_error(error, MYF(0), errmsg);
DBUG_RETURN(1);
} }
#endif /* NDB_DISKDATA */

View File

@ -511,6 +511,7 @@ class ha_ndbcluster: public handler
bool eq_range, bool sorted, bool eq_range, bool sorted,
byte* buf); byte* buf);
int read_range_next(); int read_range_next();
int alter_tablespace(st_alter_tablespace *info);
/** /**
* Multi range stuff * Multi range stuff

View File

@ -96,6 +96,7 @@ handlerton partition_hton = {
NULL, /* Start Consistent Snapshot */ NULL, /* Start Consistent Snapshot */
NULL, /* Flush logs */ NULL, /* Flush logs */
NULL, /* Show status */ NULL, /* Show status */
NULL, /* Alter Tablespace */
HTON_NOT_USER_SELECTABLE | HTON_HIDDEN HTON_NOT_USER_SELECTABLE | HTON_HIDDEN
}; };

View File

@ -315,6 +315,82 @@ typedef struct xid_t XID;
#define MAX_XID_LIST_SIZE (1024*128) #define MAX_XID_LIST_SIZE (1024*128)
#endif #endif
/*
These structures are used to pass information from a set of SQL commands
on add/drop/change tablespace definitions to the proper hton.
*/
#define UNDEF_NODEGROUP 65535
enum ts_command_type
{
TS_CMD_NOT_DEFINED = -1,
CREATE_TABLESPACE = 0,
ALTER_TABLESPACE = 1,
CREATE_LOGFILE_GROUP = 2,
ALTER_LOGFILE_GROUP = 3,
DROP_TABLESPACE = 4,
DROP_LOGFILE_GROUP = 5,
CHANGE_FILE_TABLESPACE = 6,
ALTER_ACCESS_MODE_TABLESPACE = 7
};
enum ts_alter_tablespace_type
{
TS_ALTER_TABLESPACE_TYPE_NOT_DEFINED = -1,
ALTER_TABLESPACE_ADD_FILE = 1,
ALTER_TABLESPACE_DROP_FILE = 2
};
enum tablespace_access_mode
{
TS_NOT_DEFINED= -1,
TS_READ_ONLY = 0,
TS_READ_WRITE = 1,
TS_NOT_ACCESSIBLE = 2
};
class st_alter_tablespace : public Sql_alloc
{
public:
const char *tablespace_name;
const char *logfile_group_name;
enum ts_command_type ts_cmd_type;
enum ts_alter_tablespace_type ts_alter_tablespace_type;
const char *data_file_name;
const char *undo_file_name;
const char *redo_file_name;
ulonglong extent_size;
ulonglong undo_buffer_size;
ulonglong redo_buffer_size;
ulonglong initial_size;
ulonglong autoextend_size;
ulonglong max_size;
uint nodegroup_id;
enum legacy_db_type storage_engine;
bool wait_until_completed;
const char *ts_comment;
enum tablespace_access_mode ts_access_mode;
st_alter_tablespace()
{
tablespace_name= NULL;
logfile_group_name= "DEFAULT_LG"; //Default log file group
ts_cmd_type= TS_CMD_NOT_DEFINED;
data_file_name= NULL;
undo_file_name= NULL;
redo_file_name= NULL;
extent_size= 1024*1024; //Default 1 MByte
undo_buffer_size= 8*1024*1024; //Default 8 MByte
redo_buffer_size= 8*1024*1024; //Default 8 MByte
initial_size= 128*1024*1024; //Default 128 MByte
autoextend_size= 0; //No autoextension as default
max_size= 0; //Max size == initial size => no extension
storage_engine= DB_TYPE_UNKNOWN;
nodegroup_id= UNDEF_NODEGROUP;
wait_until_completed= TRUE;
ts_comment= NULL;
ts_access_mode= TS_NOT_DEFINED;
}
};
/* The handler for a table type. Will be included in the TABLE structure */ /* The handler for a table type. Will be included in the TABLE structure */
struct st_table; struct st_table;
@ -434,6 +510,7 @@ typedef struct
int (*start_consistent_snapshot)(THD *thd); int (*start_consistent_snapshot)(THD *thd);
bool (*flush_logs)(); bool (*flush_logs)();
bool (*show_status)(THD *thd, stat_print_fn *print, enum ha_stat_type stat); bool (*show_status)(THD *thd, stat_print_fn *print, enum ha_stat_type stat);
int (*alter_tablespace)(THD *thd, st_alter_tablespace *ts_info);
uint32 flags; /* global handler flags */ uint32 flags; /* global handler flags */
} handlerton; } handlerton;
@ -732,7 +809,7 @@ typedef struct st_ha_create_information
{ {
CHARSET_INFO *table_charset, *default_table_charset; CHARSET_INFO *table_charset, *default_table_charset;
LEX_STRING connect_string; LEX_STRING connect_string;
const char *comment,*password; const char *comment,*password, *tablespace;
const char *data_file_name, *index_file_name; const char *data_file_name, *index_file_name;
const char *alias; const char *alias;
ulonglong max_rows,min_rows; ulonglong max_rows,min_rows;
@ -752,6 +829,7 @@ typedef struct st_ha_create_information
bool table_existed; /* 1 in create if table existed */ bool table_existed; /* 1 in create if table existed */
bool frm_only; /* 1 if no ha_create_table() */ bool frm_only; /* 1 if no ha_create_table() */
bool varchar; /* 1 if table has a VARCHAR */ bool varchar; /* 1 if table has a VARCHAR */
bool store_on_disk; /* 1 if table stored on disk */
} HA_CREATE_INFO; } HA_CREATE_INFO;
@ -830,7 +908,6 @@ typedef struct st_handler_buffer
byte *end_of_used_area; /* End of area that was used by handler */ byte *end_of_used_area; /* End of area that was used by handler */
} HANDLER_BUFFER; } HANDLER_BUFFER;
class handler :public Sql_alloc class handler :public Sql_alloc
{ {
#ifdef WITH_PARTITION_STORAGE_ENGINE #ifdef WITH_PARTITION_STORAGE_ENGINE

View File

@ -59,6 +59,7 @@ static SYMBOL symbols[] = {
{ "<<", SYM(SHIFT_LEFT)}, { "<<", SYM(SHIFT_LEFT)},
{ ">>", SYM(SHIFT_RIGHT)}, { ">>", SYM(SHIFT_RIGHT)},
{ "<=>", SYM(EQUAL_SYM)}, { "<=>", SYM(EQUAL_SYM)},
{ "ACCESSIBLE", SYM(ACCESSIBLE_SYM)},
{ "ACTION", SYM(ACTION)}, { "ACTION", SYM(ACTION)},
{ "ADD", SYM(ADD)}, { "ADD", SYM(ADD)},
{ "AFTER", SYM(AFTER_SYM)}, { "AFTER", SYM(AFTER_SYM)},
@ -76,6 +77,7 @@ static SYMBOL symbols[] = {
{ "ASENSITIVE", SYM(ASENSITIVE_SYM)}, { "ASENSITIVE", SYM(ASENSITIVE_SYM)},
{ "AUTHORS", SYM(AUTHORS_SYM)}, { "AUTHORS", SYM(AUTHORS_SYM)},
{ "AUTO_INCREMENT", SYM(AUTO_INC)}, { "AUTO_INCREMENT", SYM(AUTO_INC)},
{ "AUTOEXTEND_SIZE", SYM(AUTOEXTEND_SIZE_SYM)},
{ "AVG", SYM(AVG_SYM)}, { "AVG", SYM(AVG_SYM)},
{ "AVG_ROW_LENGTH", SYM(AVG_ROW_LENGTH)}, { "AVG_ROW_LENGTH", SYM(AVG_ROW_LENGTH)},
{ "BACKUP", SYM(BACKUP_SYM)}, { "BACKUP", SYM(BACKUP_SYM)},
@ -141,6 +143,7 @@ static SYMBOL symbols[] = {
{ "DATA", SYM(DATA_SYM)}, { "DATA", SYM(DATA_SYM)},
{ "DATABASE", SYM(DATABASE)}, { "DATABASE", SYM(DATABASE)},
{ "DATABASES", SYM(DATABASES)}, { "DATABASES", SYM(DATABASES)},
{ "DATAFILE", SYM(DATAFILE_SYM)},
{ "DATE", SYM(DATE_SYM)}, { "DATE", SYM(DATE_SYM)},
{ "DATETIME", SYM(DATETIME)}, { "DATETIME", SYM(DATETIME)},
{ "DAY", SYM(DAY_SYM)}, { "DAY", SYM(DAY_SYM)},
@ -164,6 +167,7 @@ static SYMBOL symbols[] = {
{ "DIRECTORY", SYM(DIRECTORY_SYM)}, { "DIRECTORY", SYM(DIRECTORY_SYM)},
{ "DISABLE", SYM(DISABLE_SYM)}, { "DISABLE", SYM(DISABLE_SYM)},
{ "DISCARD", SYM(DISCARD)}, { "DISCARD", SYM(DISCARD)},
{ "DISK", SYM(DISK_SYM)},
{ "DISTINCT", SYM(DISTINCT)}, { "DISTINCT", SYM(DISTINCT)},
{ "DISTINCTROW", SYM(DISTINCT)}, /* Access likes this */ { "DISTINCTROW", SYM(DISTINCT)}, /* Access likes this */
{ "DIV", SYM(DIV_SYM)}, { "DIV", SYM(DIV_SYM)},
@ -193,6 +197,7 @@ static SYMBOL symbols[] = {
{ "EXPANSION", SYM(EXPANSION_SYM)}, { "EXPANSION", SYM(EXPANSION_SYM)},
{ "EXPLAIN", SYM(DESCRIBE)}, { "EXPLAIN", SYM(DESCRIBE)},
{ "EXTENDED", SYM(EXTENDED_SYM)}, { "EXTENDED", SYM(EXTENDED_SYM)},
{ "EXTENT_SIZE", SYM(EXTENT_SIZE_SYM)},
{ "FALSE", SYM(FALSE_SYM)}, { "FALSE", SYM(FALSE_SYM)},
{ "FAST", SYM(FAST_SYM)}, { "FAST", SYM(FAST_SYM)},
{ "FETCH", SYM(FETCH_SYM)}, { "FETCH", SYM(FETCH_SYM)},
@ -241,6 +246,7 @@ static SYMBOL symbols[] = {
{ "INDEX", SYM(INDEX_SYM)}, { "INDEX", SYM(INDEX_SYM)},
{ "INDEXES", SYM(INDEXES)}, { "INDEXES", SYM(INDEXES)},
{ "INFILE", SYM(INFILE)}, { "INFILE", SYM(INFILE)},
{ "INITIAL_SIZE", SYM(INITIAL_SIZE_SYM)},
{ "INNER", SYM(INNER_SYM)}, { "INNER", SYM(INNER_SYM)},
{ "INNOBASE", SYM(INNOBASE_SYM)}, { "INNOBASE", SYM(INNOBASE_SYM)},
{ "INNODB", SYM(INNOBASE_SYM)}, { "INNODB", SYM(INNOBASE_SYM)},
@ -292,6 +298,7 @@ static SYMBOL symbols[] = {
{ "LOCALTIMESTAMP", SYM(NOW_SYM)}, { "LOCALTIMESTAMP", SYM(NOW_SYM)},
{ "LOCK", SYM(LOCK_SYM)}, { "LOCK", SYM(LOCK_SYM)},
{ "LOCKS", SYM(LOCKS_SYM)}, { "LOCKS", SYM(LOCKS_SYM)},
{ "LOGFILE", SYM(LOGFILE_SYM)},
{ "LOGS", SYM(LOGS_SYM)}, { "LOGS", SYM(LOGS_SYM)},
{ "LONG", SYM(LONG_SYM)}, { "LONG", SYM(LONG_SYM)},
{ "LONGBLOB", SYM(LONGBLOB)}, { "LONGBLOB", SYM(LONGBLOB)},
@ -317,6 +324,7 @@ static SYMBOL symbols[] = {
{ "MAX_CONNECTIONS_PER_HOUR", SYM(MAX_CONNECTIONS_PER_HOUR)}, { "MAX_CONNECTIONS_PER_HOUR", SYM(MAX_CONNECTIONS_PER_HOUR)},
{ "MAX_QUERIES_PER_HOUR", SYM(MAX_QUERIES_PER_HOUR)}, { "MAX_QUERIES_PER_HOUR", SYM(MAX_QUERIES_PER_HOUR)},
{ "MAX_ROWS", SYM(MAX_ROWS)}, { "MAX_ROWS", SYM(MAX_ROWS)},
{ "MAX_SIZE", SYM(MAX_SIZE_SYM)},
{ "MAX_UPDATES_PER_HOUR", SYM(MAX_UPDATES_PER_HOUR)}, { "MAX_UPDATES_PER_HOUR", SYM(MAX_UPDATES_PER_HOUR)},
{ "MAX_USER_CONNECTIONS", SYM(MAX_USER_CONNECTIONS_SYM)}, { "MAX_USER_CONNECTIONS", SYM(MAX_USER_CONNECTIONS_SYM)},
{ "MAXVALUE", SYM(MAX_VALUE_SYM)}, { "MAXVALUE", SYM(MAX_VALUE_SYM)},
@ -324,6 +332,7 @@ static SYMBOL symbols[] = {
{ "MEDIUMBLOB", SYM(MEDIUMBLOB)}, { "MEDIUMBLOB", SYM(MEDIUMBLOB)},
{ "MEDIUMINT", SYM(MEDIUMINT)}, { "MEDIUMINT", SYM(MEDIUMINT)},
{ "MEDIUMTEXT", SYM(MEDIUMTEXT)}, { "MEDIUMTEXT", SYM(MEDIUMTEXT)},
{ "MEMORY", SYM(MEMORY_SYM)},
{ "MERGE", SYM(MERGE_SYM)}, { "MERGE", SYM(MERGE_SYM)},
{ "MICROSECOND", SYM(MICROSECOND_SYM)}, { "MICROSECOND", SYM(MICROSECOND_SYM)},
{ "MIDDLEINT", SYM(MEDIUMINT)}, /* For powerbuilder */ { "MIDDLEINT", SYM(MEDIUMINT)}, /* For powerbuilder */
@ -351,6 +360,7 @@ static SYMBOL symbols[] = {
{ "NEW", SYM(NEW_SYM)}, { "NEW", SYM(NEW_SYM)},
{ "NEXT", SYM(NEXT_SYM)}, { "NEXT", SYM(NEXT_SYM)},
{ "NO", SYM(NO_SYM)}, { "NO", SYM(NO_SYM)},
{ "NO_WAIT", SYM(NO_WAIT_SYM)},
{ "NODEGROUP", SYM(NODEGROUP_SYM)}, { "NODEGROUP", SYM(NODEGROUP_SYM)},
{ "NONE", SYM(NONE_SYM)}, { "NONE", SYM(NONE_SYM)},
{ "NOT", SYM(NOT_SYM)}, { "NOT", SYM(NOT_SYM)},
@ -400,9 +410,13 @@ static SYMBOL symbols[] = {
{ "RAID_TYPE", SYM(RAID_TYPE)}, { "RAID_TYPE", SYM(RAID_TYPE)},
{ "RANGE", SYM(RANGE_SYM)}, { "RANGE", SYM(RANGE_SYM)},
{ "READ", SYM(READ_SYM)}, { "READ", SYM(READ_SYM)},
{ "READ_ONLY", SYM(READ_ONLY_SYM)},
{ "READ_WRITE", SYM(READ_WRITE_SYM)},
{ "READS", SYM(READS_SYM)}, { "READS", SYM(READS_SYM)},
{ "REAL", SYM(REAL)}, { "REAL", SYM(REAL)},
{ "RECOVER", SYM(RECOVER_SYM)}, { "RECOVER", SYM(RECOVER_SYM)},
{ "REDO_BUFFER_SIZE", SYM(REDO_BUFFER_SIZE_SYM)},
{ "REDOFILE", SYM(REDOFILE_SYM)},
{ "REDUNDANT", SYM(REDUNDANT_SYM)}, { "REDUNDANT", SYM(REDUNDANT_SYM)},
{ "REFERENCES", SYM(REFERENCES)}, { "REFERENCES", SYM(REFERENCES)},
{ "REGEXP", SYM(REGEXP)}, { "REGEXP", SYM(REGEXP)},
@ -522,6 +536,8 @@ static SYMBOL symbols[] = {
{ "TYPES", SYM(TYPES_SYM)}, { "TYPES", SYM(TYPES_SYM)},
{ "UNCOMMITTED", SYM(UNCOMMITTED_SYM)}, { "UNCOMMITTED", SYM(UNCOMMITTED_SYM)},
{ "UNDEFINED", SYM(UNDEFINED_SYM)}, { "UNDEFINED", SYM(UNDEFINED_SYM)},
{ "UNDO_BUFFER_SIZE", SYM(UNDO_BUFFER_SIZE_SYM)},
{ "UNDOFILE", SYM(UNDOFILE_SYM)},
{ "UNDO", SYM(UNDO_SYM)}, { "UNDO", SYM(UNDO_SYM)},
{ "UNICODE", SYM(UNICODE_SYM)}, { "UNICODE", SYM(UNICODE_SYM)},
{ "UNION", SYM(UNION_SYM)}, { "UNION", SYM(UNION_SYM)},
@ -548,6 +564,7 @@ static SYMBOL symbols[] = {
{ "VARCHARACTER", SYM(VARCHAR)}, { "VARCHARACTER", SYM(VARCHAR)},
{ "VARIABLES", SYM(VARIABLES)}, { "VARIABLES", SYM(VARIABLES)},
{ "VARYING", SYM(VARYING)}, { "VARYING", SYM(VARYING)},
{ "WAIT", SYM(WAIT_SYM)},
{ "WARNINGS", SYM(WARNINGS)}, { "WARNINGS", SYM(WARNINGS)},
{ "WEEK", SYM(WEEK_SYM)}, { "WEEK", SYM(WEEK_SYM)},
{ "WHEN", SYM(WHEN_SYM)}, { "WHEN", SYM(WHEN_SYM)},

View File

@ -88,6 +88,7 @@ handlerton binlog_hton = {
NULL, /* Start Consistent Snapshot */ NULL, /* Start Consistent Snapshot */
NULL, /* Flush logs */ NULL, /* Flush logs */
NULL, /* Show status */ NULL, /* Show status */
NULL, /* Alter Tablespace */
HTON_NOT_USER_SELECTABLE | HTON_HIDDEN HTON_NOT_USER_SELECTABLE | HTON_HIDDEN
}; };

View File

@ -691,6 +691,7 @@ TABLE *create_virtual_tmp_table(THD *thd, List<create_field> &field_list);
bool mysql_xa_recover(THD *thd); bool mysql_xa_recover(THD *thd);
bool check_simple_select(); bool check_simple_select();
int mysql_alter_tablespace(THD* thd, st_alter_tablespace *ts_info);
SORT_FIELD * make_unireg_sortorder(ORDER *order, uint *length); SORT_FIELD * make_unireg_sortorder(ORDER *order, uint *length);
int setup_order(THD *thd, Item **ref_pointer_array, TABLE_LIST *tables, int setup_order(THD *thd, Item **ref_pointer_array, TABLE_LIST *tables,

View File

@ -5727,6 +5727,20 @@ ER_WRONG_VALUE
eng "Incorrect %-.32s value: '%-.128s'" eng "Incorrect %-.32s value: '%-.128s'"
ER_NO_PARTITION_FOR_GIVEN_VALUE ER_NO_PARTITION_FOR_GIVEN_VALUE
eng "Table has no partition for value %ld" eng "Table has no partition for value %ld"
ER_TABLESPACE_OPTION_ONLY_ONCE
eng "It is not allowed to specify %s more than once"
ER_CREATE_TABLESPACE_FAILED
eng "Failed to create %s"
ER_DROP_TABLESPACE_FAILED
eng "Failed to drop %s"
ER_TABLESPACE_AUTO_EXTEND_ERROR
eng "The handler doesn't support autoextend of tablespaces"
ER_WRONG_SIZE_NUMBER
eng "A size parameter was incorrectly specified, either number or on the form 10M"
ER_SIZE_OVERFLOW_ERROR
eng "The size number was correct but we don't allow the digit part to be more than 2 billion"
ER_ALTER_TABLESPACE_FAILED
eng "Failed to alter: %s"
ER_BINLOG_ROW_LOGGING_FAILED ER_BINLOG_ROW_LOGGING_FAILED
eng "Writing one row to the row-based binary log failed" eng "Writing one row to the row-based binary log failed"
ER_BINLOG_ROW_WRONG_TABLE_DEF ER_BINLOG_ROW_WRONG_TABLE_DEF

View File

@ -25,6 +25,7 @@ class sp_head;
class sp_name; class sp_name;
class sp_instr; class sp_instr;
class sp_pcontext; class sp_pcontext;
class st_alter_tablespace;
class partition_info; class partition_info;
/* /*
@ -92,6 +93,7 @@ enum enum_sql_command {
SQLCOM_XA_START, SQLCOM_XA_END, SQLCOM_XA_PREPARE, SQLCOM_XA_START, SQLCOM_XA_END, SQLCOM_XA_PREPARE,
SQLCOM_XA_COMMIT, SQLCOM_XA_ROLLBACK, SQLCOM_XA_RECOVER, SQLCOM_XA_COMMIT, SQLCOM_XA_ROLLBACK, SQLCOM_XA_RECOVER,
SQLCOM_SHOW_PROC_CODE, SQLCOM_SHOW_FUNC_CODE, SQLCOM_SHOW_PROC_CODE, SQLCOM_SHOW_FUNC_CODE,
SQLCOM_ALTER_TABLESPACE,
SQLCOM_INSTALL_PLUGIN, SQLCOM_UNINSTALL_PLUGIN, SQLCOM_INSTALL_PLUGIN, SQLCOM_UNINSTALL_PLUGIN,
SQLCOM_SHOW_AUTHORS, SQLCOM_BINLOG_BASE64_EVENT, SQLCOM_SHOW_AUTHORS, SQLCOM_BINLOG_BASE64_EVENT,
SQLCOM_SHOW_PLUGINS, SQLCOM_SHOW_PLUGINS,
@ -953,6 +955,12 @@ typedef struct st_lex
*/ */
const uchar *fname_start, *fname_end; const uchar *fname_start, *fname_end;
/*
Reference to a struct that contains information in various commands
to add/create/drop/change table spaces.
*/
st_alter_tablespace *alter_tablespace_info;
bool escape_used; bool escape_used;
st_lex(); st_lex();

View File

@ -4818,6 +4818,12 @@ end_with_restore_list:
case SQLCOM_XA_RECOVER: case SQLCOM_XA_RECOVER:
res= mysql_xa_recover(thd); res= mysql_xa_recover(thd);
break; break;
case SQLCOM_ALTER_TABLESPACE:
if (check_access(thd, ALTER_ACL, thd->db, 0, 1, 0, thd->db ? is_schema_db(thd->db) : 0))
break;
if (!(res= mysql_alter_tablespace(thd, lex->alter_tablespace_info)))
send_ok(thd);
break;
case SQLCOM_INSTALL_PLUGIN: case SQLCOM_INSTALL_PLUGIN:
if (! (res= mysql_install_plugin(thd, &thd->lex->comment, if (! (res= mysql_install_plugin(thd, &thd->lex->comment,
&thd->lex->ident))) &thd->lex->ident)))

50
sql/sql_tablespace.cc Normal file
View File

@ -0,0 +1,50 @@
/* Copyright (C) 2000-2004 MySQL AB
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
/* drop and alter of tablespaces */
#include "mysql_priv.h"
int mysql_alter_tablespace(THD *thd, st_alter_tablespace *ts_info)
{
int error= HA_ADMIN_NOT_IMPLEMENTED;
handlerton *hton;
DBUG_ENTER("mysql_alter_tablespace");
/*
If the user haven't defined an engine, this will fallback to using the
default storage engine.
*/
hton= ha_resolve_by_legacy_type(thd, ts_info->storage_engine);
if (hton->alter_tablespace && (error= hton->alter_tablespace(thd, ts_info)))
{
if (error == HA_ADMIN_NOT_IMPLEMENTED)
{
my_error(ER_CHECK_NOT_IMPLEMENTED, MYF(0), "");
}
else if (error == 1)
{
DBUG_RETURN(1);
}
else
{
my_error(error, MYF(0));
}
DBUG_RETURN(error);
}
DBUG_RETURN(FALSE);
}

View File

@ -119,6 +119,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b, ulong *yystacksize);
%token END_OF_INPUT %token END_OF_INPUT
%token ABORT_SYM %token ABORT_SYM
%token ACCESSIBLE_SYM
%token ACTION %token ACTION
%token ADD %token ADD
%token ADDDATE_SYM %token ADDDATE_SYM
@ -139,6 +140,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b, ulong *yystacksize);
%token ATAN %token ATAN
%token AUTHORS_SYM %token AUTHORS_SYM
%token AUTO_INC %token AUTO_INC
%token AUTOEXTEND_SIZE_SYM
%token AVG_ROW_LENGTH %token AVG_ROW_LENGTH
%token AVG_SYM %token AVG_SYM
%token BACKUP_SYM %token BACKUP_SYM
@ -208,6 +210,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b, ulong *yystacksize);
%token CURTIME %token CURTIME
%token DATABASE %token DATABASE
%token DATABASES %token DATABASES
%token DATAFILE_SYM
%token DATA_SYM %token DATA_SYM
%token DATETIME %token DATETIME
%token DATE_ADD_INTERVAL %token DATE_ADD_INTERVAL
@ -237,6 +240,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b, ulong *yystacksize);
%token DIRECTORY_SYM %token DIRECTORY_SYM
%token DISABLE_SYM %token DISABLE_SYM
%token DISCARD %token DISCARD
%token DISK_SYM
%token DISTINCT %token DISTINCT
%token DIV_SYM %token DIV_SYM
%token DOUBLE_SYM %token DOUBLE_SYM
@ -269,6 +273,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b, ulong *yystacksize);
%token EXPANSION_SYM %token EXPANSION_SYM
%token EXPORT_SET %token EXPORT_SET
%token EXTENDED_SYM %token EXTENDED_SYM
%token EXTENT_SIZE_SYM
%token EXTRACT_SYM %token EXTRACT_SYM
%token FALSE_SYM %token FALSE_SYM
%token FAST_SYM %token FAST_SYM
@ -331,6 +336,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b, ulong *yystacksize);
%token INDEXES %token INDEXES
%token INDEX_SYM %token INDEX_SYM
%token INFILE %token INFILE
%token INITIAL_SIZE_SYM
%token INNER_SYM %token INNER_SYM
%token INNOBASE_SYM %token INNOBASE_SYM
%token INOUT_SYM %token INOUT_SYM
@ -377,6 +383,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b, ulong *yystacksize);
%token LOCATOR_SYM %token LOCATOR_SYM
%token LOCKS_SYM %token LOCKS_SYM
%token LOCK_SYM %token LOCK_SYM
%token LOGFILE_SYM
%token LOGS_SYM %token LOGS_SYM
%token LOG_SYM %token LOG_SYM
%token LONGBLOB %token LONGBLOB
@ -407,6 +414,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b, ulong *yystacksize);
%token MAX_CONNECTIONS_PER_HOUR %token MAX_CONNECTIONS_PER_HOUR
%token MAX_QUERIES_PER_HOUR %token MAX_QUERIES_PER_HOUR
%token MAX_ROWS %token MAX_ROWS
%token MAX_SIZE_SYM
%token MAX_SYM %token MAX_SYM
%token MAX_UPDATES_PER_HOUR %token MAX_UPDATES_PER_HOUR
%token MAX_USER_CONNECTIONS_SYM %token MAX_USER_CONNECTIONS_SYM
@ -415,6 +423,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b, ulong *yystacksize);
%token MEDIUMINT %token MEDIUMINT
%token MEDIUMTEXT %token MEDIUMTEXT
%token MEDIUM_SYM %token MEDIUM_SYM
%token MEMORY_SYM
%token MERGE_SYM %token MERGE_SYM
%token MICROSECOND_SYM %token MICROSECOND_SYM
%token MIGRATE_SYM %token MIGRATE_SYM
@ -451,6 +460,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b, ulong *yystacksize);
%token NOT_SYM %token NOT_SYM
%token NOW_SYM %token NOW_SYM
%token NO_SYM %token NO_SYM
%token NO_WAIT_SYM
%token NO_WRITE_TO_BINLOG %token NO_WRITE_TO_BINLOG
%token NULL_SYM %token NULL_SYM
%token NUM %token NUM
@ -506,9 +516,13 @@ bool my_yyoverflow(short **a, YYSTYPE **b, ulong *yystacksize);
%token RAND %token RAND
%token RANGE_SYM %token RANGE_SYM
%token READS_SYM %token READS_SYM
%token READ_ONLY_SYM
%token READ_SYM %token READ_SYM
%token READ_WRITE_SYM
%token REAL %token REAL
%token RECOVER_SYM %token RECOVER_SYM
%token REDO_BUFFER_SIZE_SYM
%token REDOFILE_SYM
%token REDUNDANT_SYM %token REDUNDANT_SYM
%token REFERENCES %token REFERENCES
%token REGEXP %token REGEXP
@ -630,6 +644,8 @@ bool my_yyoverflow(short **a, YYSTYPE **b, ulong *yystacksize);
%token ULONGLONG_NUM %token ULONGLONG_NUM
%token UNCOMMITTED_SYM %token UNCOMMITTED_SYM
%token UNDEFINED_SYM %token UNDEFINED_SYM
%token UNDO_BUFFER_SIZE_SYM
%token UNDOFILE_SYM
%token UNDERSCORE_CHARSET %token UNDERSCORE_CHARSET
%token UNDO_SYM %token UNDO_SYM
%token UNICODE_SYM %token UNICODE_SYM
@ -660,6 +676,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b, ulong *yystacksize);
%token VARIANCE_SYM %token VARIANCE_SYM
%token VARYING %token VARYING
%token VIEW_SYM %token VIEW_SYM
%token WAIT_SYM
%token WARNINGS %token WARNINGS
%token WEEK_SYM %token WEEK_SYM
%token WHEN_SYM %token WHEN_SYM
@ -727,7 +744,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b, ulong *yystacksize);
ulong_num raid_types merge_insert_types ulong_num raid_types merge_insert_types
%type <ulonglong_number> %type <ulonglong_number>
ulonglong_num ulonglong_num size_number
%type <longlong_number> %type <longlong_number>
part_bit_expr part_bit_expr
@ -1296,6 +1313,16 @@ create:
{ {
Lex->sql_command = SQLCOM_CREATE_USER; Lex->sql_command = SQLCOM_CREATE_USER;
} }
| CREATE LOGFILE_SYM GROUP logfile_group_info
{
LEX *lex= Lex;
lex->alter_tablespace_info->ts_cmd_type= CREATE_LOGFILE_GROUP;
}
| CREATE TABLESPACE tablespace_info
{
LEX *lex= Lex;
lex->alter_tablespace_info->ts_cmd_type= CREATE_TABLESPACE;
}
; ;
clear_privileges: clear_privileges:
@ -2538,6 +2565,382 @@ trg_event:
| DELETE_SYM | DELETE_SYM
{ Lex->trg_chistics.event= TRG_EVENT_DELETE; } { Lex->trg_chistics.event= TRG_EVENT_DELETE; }
; ;
/*
This part of the parser contains common code for all TABLESPACE
commands.
CREATE TABLESPACE name ...
ALTER TABLESPACE name CHANGE DATAFILE ...
ALTER TABLESPACE name ADD DATAFILE ...
ALTER TABLESPACE name access_mode
CREATE LOGFILE GROUP name ...
ALTER LOGFILE GROUP name ADD UNDOFILE ..
ALTER LOGFILE GROUP name ADD REDOFILE ..
DROP TABLESPACE name
DROP LOGFILE GROUP name
*/
change_tablespace_access:
tablespace_name
ts_access_mode
;
change_tablespace_info:
tablespace_name
CHANGE ts_datafile
change_ts_option_list
;
tablespace_info:
tablespace_name
ADD ts_datafile
opt_logfile_group_name
tablespace_option_list
;
opt_logfile_group_name:
/* empty */ {}
| USE_SYM LOGFILE_SYM GROUP ident
{
LEX *lex= Lex;
lex->alter_tablespace_info->logfile_group_name= $4.str;
};
alter_tablespace_info:
tablespace_name
ADD ts_datafile
alter_tablespace_option_list
{
Lex->alter_tablespace_info->ts_alter_tablespace_type= ALTER_TABLESPACE_ADD_FILE;
}
|
tablespace_name
DROP ts_datafile
alter_tablespace_option_list
{
Lex->alter_tablespace_info->ts_alter_tablespace_type= ALTER_TABLESPACE_DROP_FILE;
};
logfile_group_info:
logfile_group_name
add_log_file
logfile_group_option_list
;
alter_logfile_group_info:
logfile_group_name
add_log_file
alter_logfile_group_option_list
;
add_log_file:
ADD lg_undofile
| ADD lg_redofile
;
change_ts_option_list:
/* empty */ {}
change_ts_options
;
change_ts_options:
change_ts_option
| change_ts_options change_ts_option
| change_ts_options ',' change_ts_option
;
change_ts_option:
opt_ts_initial_size
| opt_ts_autoextend_size
| opt_ts_max_size
;
tablespace_option_list:
/* empty */ {}
tablespace_options
;
tablespace_options:
tablespace_option
| tablespace_options tablespace_option
| tablespace_options ',' tablespace_option
;
tablespace_option:
opt_ts_initial_size
| opt_ts_autoextend_size
| opt_ts_max_size
| opt_ts_extent_size
| opt_ts_nodegroup
| opt_ts_engine
| ts_wait
| opt_ts_comment
;
alter_tablespace_option_list:
/* empty */ {}
alter_tablespace_options
;
alter_tablespace_options:
alter_tablespace_option
| alter_tablespace_options alter_tablespace_option
| alter_tablespace_options ',' alter_tablespace_option
;
alter_tablespace_option:
opt_ts_initial_size
| opt_ts_autoextend_size
| opt_ts_max_size
| opt_ts_engine
| ts_wait
;
logfile_group_option_list:
/* empty */ {}
logfile_group_options
;
logfile_group_options:
logfile_group_option
| logfile_group_options logfile_group_option
| logfile_group_options ',' logfile_group_option
;
logfile_group_option:
opt_ts_initial_size
| opt_ts_undo_buffer_size
| opt_ts_redo_buffer_size
| opt_ts_nodegroup
| opt_ts_engine
| ts_wait
| opt_ts_comment
;
alter_logfile_group_option_list:
/* empty */ {}
alter_logfile_group_options
;
alter_logfile_group_options:
alter_logfile_group_option
| alter_logfile_group_options alter_logfile_group_option
| alter_logfile_group_options ',' alter_logfile_group_option
;
alter_logfile_group_option:
opt_ts_initial_size
| opt_ts_engine
| ts_wait
;
ts_datafile:
DATAFILE_SYM TEXT_STRING_sys
{
LEX *lex= Lex;
lex->alter_tablespace_info->data_file_name= $2.str;
};
lg_undofile:
UNDOFILE_SYM TEXT_STRING_sys
{
LEX *lex= Lex;
lex->alter_tablespace_info->undo_file_name= $2.str;
};
lg_redofile:
REDOFILE_SYM TEXT_STRING_sys
{
LEX *lex= Lex;
lex->alter_tablespace_info->redo_file_name= $2.str;
};
tablespace_name:
ident
{
LEX *lex= Lex;
lex->alter_tablespace_info= new st_alter_tablespace();
lex->alter_tablespace_info->tablespace_name= $1.str;
lex->sql_command= SQLCOM_ALTER_TABLESPACE;
};
logfile_group_name:
ident
{
LEX *lex= Lex;
lex->alter_tablespace_info= new st_alter_tablespace();
lex->alter_tablespace_info->logfile_group_name= $1.str;
lex->sql_command= SQLCOM_ALTER_TABLESPACE;
};
ts_access_mode:
READ_ONLY_SYM
{
LEX *lex= Lex;
lex->alter_tablespace_info->ts_access_mode= TS_READ_ONLY;
}
| READ_WRITE_SYM
{
LEX *lex= Lex;
lex->alter_tablespace_info->ts_access_mode= TS_READ_WRITE;
}
| NOT_SYM ACCESSIBLE_SYM
{
LEX *lex= Lex;
lex->alter_tablespace_info->ts_access_mode= TS_NOT_ACCESSIBLE;
};
opt_ts_initial_size:
INITIAL_SIZE_SYM opt_equal size_number
{
LEX *lex= Lex;
lex->alter_tablespace_info->initial_size= $3;
};
opt_ts_autoextend_size:
AUTOEXTEND_SIZE_SYM opt_equal size_number
{
LEX *lex= Lex;
lex->alter_tablespace_info->autoextend_size= $3;
};
opt_ts_max_size:
MAX_SIZE_SYM opt_equal size_number
{
LEX *lex= Lex;
lex->alter_tablespace_info->max_size= $3;
};
opt_ts_extent_size:
EXTENT_SIZE_SYM opt_equal size_number
{
LEX *lex= Lex;
lex->alter_tablespace_info->extent_size= $3;
};
opt_ts_undo_buffer_size:
UNDO_BUFFER_SIZE_SYM opt_equal size_number
{
LEX *lex= Lex;
lex->alter_tablespace_info->undo_buffer_size= $3;
};
opt_ts_redo_buffer_size:
REDO_BUFFER_SIZE_SYM opt_equal size_number
{
LEX *lex= Lex;
lex->alter_tablespace_info->redo_buffer_size= $3;
};
opt_ts_nodegroup:
NODEGROUP_SYM opt_equal ulong_num
{
LEX *lex= Lex;
if (lex->alter_tablespace_info->nodegroup_id != UNDEF_NODEGROUP)
{
my_error(ER_TABLESPACE_OPTION_ONLY_ONCE,MYF(0),"NODEGROUP");
YYABORT;
}
lex->alter_tablespace_info->nodegroup_id= $3;
};
opt_ts_comment:
COMMENT_SYM opt_equal TEXT_STRING_sys
{
LEX *lex= Lex;
if (lex->alter_tablespace_info->ts_comment != NULL)
{
my_error(ER_TABLESPACE_OPTION_ONLY_ONCE,MYF(0),"COMMENT");
YYABORT;
}
lex->alter_tablespace_info->ts_comment= $3.str;
};
opt_ts_engine:
opt_storage ENGINE_SYM opt_equal storage_engines
{
LEX *lex= Lex;
if (lex->alter_tablespace_info->storage_engine != DB_TYPE_UNKNOWN)
{
my_error(ER_TABLESPACE_OPTION_ONLY_ONCE,MYF(0),
"STORAGE ENGINE");
YYABORT;
}
lex->alter_tablespace_info->storage_engine= $4->db_type;
};
opt_ts_wait:
/* empty */
| ts_wait
;
ts_wait:
WAIT_SYM
{
LEX *lex= Lex;
lex->alter_tablespace_info->wait_until_completed= TRUE;
}
| NO_WAIT_SYM
{
LEX *lex= Lex;
if (!(lex->alter_tablespace_info->wait_until_completed))
{
my_error(ER_TABLESPACE_OPTION_ONLY_ONCE,MYF(0),"NO_WAIT");
YYABORT;
}
lex->alter_tablespace_info->wait_until_completed= FALSE;
};
size_number:
ulong_num { $$= $1;}
| IDENT
{
ulonglong number, test_number;
uint text_shift_number= 0;
longlong prefix_number;
char *end_ptr;
char *start_ptr= $1.str;
uint str_len= strlen(start_ptr);
int error;
prefix_number= my_strtoll10(start_ptr, &end_ptr, &error);
if ((start_ptr + str_len - 1) == end_ptr)
{
switch (end_ptr[0])
{
case 'g':
case 'G':
text_shift_number+=10;
case 'm':
case 'M':
text_shift_number+=10;
case 'k':
case 'K':
text_shift_number+=10;
break;
default:
{
my_error(ER_WRONG_SIZE_NUMBER, MYF(0));
YYABORT;
}
}
if (prefix_number >> 31)
{
my_error(ER_SIZE_OVERFLOW_ERROR, MYF(0));
YYABORT;
}
number= prefix_number << text_shift_number;
}
else
{
my_error(ER_WRONG_SIZE_NUMBER, MYF(0));
YYABORT;
}
$$= number;
}
;
/*
End tablespace part
*/
create2: create2:
'(' create2a {} '(' create2a {}
@ -3196,6 +3599,9 @@ create_table_option:
| INSERT_METHOD opt_equal merge_insert_types { Lex->create_info.merge_insert_method= $3; Lex->create_info.used_fields|= HA_CREATE_USED_INSERT_METHOD;} | INSERT_METHOD opt_equal merge_insert_types { Lex->create_info.merge_insert_method= $3; Lex->create_info.used_fields|= HA_CREATE_USED_INSERT_METHOD;}
| DATA_SYM DIRECTORY_SYM opt_equal TEXT_STRING_sys { Lex->create_info.data_file_name= $4.str; Lex->create_info.used_fields|= HA_CREATE_USED_DATADIR; } | DATA_SYM DIRECTORY_SYM opt_equal TEXT_STRING_sys { Lex->create_info.data_file_name= $4.str; Lex->create_info.used_fields|= HA_CREATE_USED_DATADIR; }
| INDEX_SYM DIRECTORY_SYM opt_equal TEXT_STRING_sys { Lex->create_info.index_file_name= $4.str; Lex->create_info.used_fields|= HA_CREATE_USED_INDEXDIR; } | INDEX_SYM DIRECTORY_SYM opt_equal TEXT_STRING_sys { Lex->create_info.index_file_name= $4.str; Lex->create_info.used_fields|= HA_CREATE_USED_INDEXDIR; }
| TABLESPACE ident {Lex->create_info.tablespace= $2.str;}
| STORAGE_SYM DISK_SYM {Lex->create_info.store_on_disk= TRUE;}
| STORAGE_SYM MEMORY_SYM {Lex->create_info.store_on_disk= FALSE;}
| CONNECTION_SYM opt_equal TEXT_STRING_sys { Lex->create_info.connect_string.str= $3.str; Lex->create_info.connect_string.length= $3.length; Lex->create_info.used_fields|= HA_CREATE_USED_CONNECTION; } | CONNECTION_SYM opt_equal TEXT_STRING_sys { Lex->create_info.connect_string.str= $3.str; Lex->create_info.connect_string.length= $3.length; Lex->create_info.used_fields|= HA_CREATE_USED_CONNECTION; }
; ;
@ -3954,6 +4360,26 @@ alter:
} }
view_list_opt AS view_select view_check_option view_list_opt AS view_select view_check_option
{} {}
| ALTER TABLESPACE alter_tablespace_info
{
LEX *lex= Lex;
lex->alter_tablespace_info->ts_cmd_type= ALTER_TABLESPACE;
}
| ALTER LOGFILE_SYM GROUP alter_logfile_group_info
{
LEX *lex= Lex;
lex->alter_tablespace_info->ts_cmd_type= ALTER_LOGFILE_GROUP;
}
| ALTER TABLESPACE change_tablespace_info
{
LEX *lex= Lex;
lex->alter_tablespace_info->ts_cmd_type= CHANGE_FILE_TABLESPACE;
}
| ALTER TABLESPACE change_tablespace_access
{
LEX *lex= Lex;
lex->alter_tablespace_info->ts_cmd_type= ALTER_ACCESS_MODE_TABLESPACE;
}
; ;
ident_or_empty: ident_or_empty:
@ -6653,6 +7079,16 @@ drop:
lex->sql_command= SQLCOM_DROP_TRIGGER; lex->sql_command= SQLCOM_DROP_TRIGGER;
lex->spname= $3; lex->spname= $3;
} }
| DROP TABLESPACE tablespace_name opt_ts_engine opt_ts_wait
{
LEX *lex= Lex;
lex->alter_tablespace_info->ts_cmd_type= DROP_TABLESPACE;
}
| DROP LOGFILE_SYM GROUP logfile_group_name opt_ts_engine opt_ts_wait
{
LEX *lex= Lex;
lex->alter_tablespace_info->ts_cmd_type= DROP_LOGFILE_GROUP;
}
; ;
table_list: table_list:
@ -8105,6 +8541,12 @@ TEXT_STRING_literal:
ident: ident:
IDENT_sys { $$=$1; } IDENT_sys { $$=$1; }
| READ_ONLY_SYM
{
THD *thd= YYTHD;
$$.str= thd->strmake("read_only",9);
$$.length= 9;
}
| keyword | keyword
{ {
THD *thd= YYTHD; THD *thd= YYTHD;
@ -8227,6 +8669,7 @@ keyword_sp:
| ALGORITHM_SYM {} | ALGORITHM_SYM {}
| ANY_SYM {} | ANY_SYM {}
| AUTO_INC {} | AUTO_INC {}
| AUTOEXTEND_SIZE_SYM {}
| AVG_ROW_LENGTH {} | AVG_ROW_LENGTH {}
| AVG_SYM {} | AVG_SYM {}
| BERKELEY_DB_SYM {} | BERKELEY_DB_SYM {}
@ -8251,6 +8694,7 @@ keyword_sp:
| CONSISTENT_SYM {} | CONSISTENT_SYM {}
| CUBE_SYM {} | CUBE_SYM {}
| DATA_SYM {} | DATA_SYM {}
| DATAFILE_SYM {}
| DATETIME {} | DATETIME {}
| DATE_SYM {} | DATE_SYM {}
| DAY_SYM {} | DAY_SYM {}
@ -8259,6 +8703,7 @@ keyword_sp:
| DES_KEY_FILE {} | DES_KEY_FILE {}
| DIRECTORY_SYM {} | DIRECTORY_SYM {}
| DISCARD {} | DISCARD {}
| DISK_SYM {}
| DUMPFILE {} | DUMPFILE {}
| DUPLICATE_SYM {} | DUPLICATE_SYM {}
| DYNAMIC_SYM {} | DYNAMIC_SYM {}
@ -8270,6 +8715,7 @@ keyword_sp:
| EVENTS_SYM {} | EVENTS_SYM {}
| EXPANSION_SYM {} | EXPANSION_SYM {}
| EXTENDED_SYM {} | EXTENDED_SYM {}
| EXTENT_SIZE_SYM {}
| FAST_SYM {} | FAST_SYM {}
| FOUND_SYM {} | FOUND_SYM {}
| DISABLE_SYM {} | DISABLE_SYM {}
@ -8291,6 +8737,7 @@ keyword_sp:
| INVOKER_SYM {} | INVOKER_SYM {}
| IMPORT {} | IMPORT {}
| INDEXES {} | INDEXES {}
| INITIAL_SIZE_SYM {}
| ISOLATION {} | ISOLATION {}
| ISSUER_SYM {} | ISSUER_SYM {}
| INNOBASE_SYM {} | INNOBASE_SYM {}
@ -8304,6 +8751,7 @@ keyword_sp:
| LIST_SYM {} | LIST_SYM {}
| LOCAL_SYM {} | LOCAL_SYM {}
| LOCKS_SYM {} | LOCKS_SYM {}
| LOGFILE_SYM {}
| LOGS_SYM {} | LOGS_SYM {}
| MAX_ROWS {} | MAX_ROWS {}
| MASTER_SYM {} | MASTER_SYM {}
@ -8323,10 +8771,12 @@ keyword_sp:
| MASTER_SSL_KEY_SYM {} | MASTER_SSL_KEY_SYM {}
| MAX_CONNECTIONS_PER_HOUR {} | MAX_CONNECTIONS_PER_HOUR {}
| MAX_QUERIES_PER_HOUR {} | MAX_QUERIES_PER_HOUR {}
| MAX_SIZE_SYM {}
| MAX_UPDATES_PER_HOUR {} | MAX_UPDATES_PER_HOUR {}
| MAX_USER_CONNECTIONS_SYM {} | MAX_USER_CONNECTIONS_SYM {}
| MAX_VALUE_SYM {} | MAX_VALUE_SYM {}
| MEDIUM_SYM {} | MEDIUM_SYM {}
| MEMORY_SYM {}
| MERGE_SYM {} | MERGE_SYM {}
| MICROSECOND_SYM {} | MICROSECOND_SYM {}
| MIGRATE_SYM {} | MIGRATE_SYM {}
@ -8346,6 +8796,7 @@ keyword_sp:
| NDBCLUSTER_SYM {} | NDBCLUSTER_SYM {}
| NEXT_SYM {} | NEXT_SYM {}
| NEW_SYM {} | NEW_SYM {}
| NO_WAIT_SYM {}
| NODEGROUP_SYM {} | NODEGROUP_SYM {}
| NONE_SYM {} | NONE_SYM {}
| NVARCHAR_SYM {} | NVARCHAR_SYM {}
@ -8373,6 +8824,8 @@ keyword_sp:
| RAID_STRIPED_SYM {} | RAID_STRIPED_SYM {}
| RAID_TYPE {} | RAID_TYPE {}
| RECOVER_SYM {} | RECOVER_SYM {}
| REDO_BUFFER_SIZE_SYM {}
| REDOFILE_SYM {}
| REDUNDANT_SYM {} | REDUNDANT_SYM {}
| RELAY_LOG_FILE_SYM {} | RELAY_LOG_FILE_SYM {}
| RELAY_LOG_POS_SYM {} | RELAY_LOG_POS_SYM {}
@ -8429,6 +8882,8 @@ keyword_sp:
| FUNCTION_SYM {} | FUNCTION_SYM {}
| UNCOMMITTED_SYM {} | UNCOMMITTED_SYM {}
| UNDEFINED_SYM {} | UNDEFINED_SYM {}
| UNDO_BUFFER_SIZE_SYM {}
| UNDOFILE_SYM {}
| UNKNOWN_SYM {} | UNKNOWN_SYM {}
| UNTIL_SYM {} | UNTIL_SYM {}
| USER {} | USER {}
@ -8437,6 +8892,7 @@ keyword_sp:
| VIEW_SYM {} | VIEW_SYM {}
| VALUE_SYM {} | VALUE_SYM {}
| WARNINGS {} | WARNINGS {}
| WAIT_SYM {}
| WEEK_SYM {} | WEEK_SYM {}
| WORK_SYM {} | WORK_SYM {}
| X509_SYM {} | X509_SYM {}

View File

@ -88,6 +88,7 @@ handlerton tina_hton= {
NULL, /* Start Consistent Snapshot */ NULL, /* Start Consistent Snapshot */
NULL, /* Flush logs */ NULL, /* Flush logs */
NULL, /* Show status */ NULL, /* Show status */
NULL, /* Alter Tablespace */
HTON_CAN_RECREATE HTON_CAN_RECREATE
}; };

View File

@ -43,6 +43,8 @@ public:
STATIC_CONST( RECORDS_IN_RANGE = 0xFFF8 ); STATIC_CONST( RECORDS_IN_RANGE = 0xFFF8 );
STATIC_CONST( DISK_REF = 0xFFF7 ); STATIC_CONST( DISK_REF = 0xFFF7 );
STATIC_CONST( ROWID = 0xFFF6 );
STATIC_CONST( ROW_GCI = 0xFFF5 );
// NOTE: in 5.1 ctors and init take size in bytes // NOTE: in 5.1 ctors and init take size in bytes

View File

@ -570,10 +570,10 @@ extern const GlobalSignalNumber NO_OF_SIGNAL_NAMES;
#define GSN_EVENT_SUBSCRIBE_REQ 458 #define GSN_EVENT_SUBSCRIBE_REQ 458
#define GSN_EVENT_SUBSCRIBE_CONF 459 #define GSN_EVENT_SUBSCRIBE_CONF 459
#define GSN_EVENT_SUBSCRIBE_REF 460 #define GSN_EVENT_SUBSCRIBE_REF 460
#define GSN_ACC_COM_BLOCK 461 /* 461 unused */
#define GSN_ACC_COM_UNBLOCK 462 /* 462 unused */
#define GSN_TUP_COM_BLOCK 463 /* 463 unused */
#define GSN_TUP_COM_UNBLOCK 464 /* 464 unused */
#define GSN_DUMP_STATE_ORD 465 #define GSN_DUMP_STATE_ORD 465

View File

@ -24,8 +24,9 @@
* via ACCKEYCONF. * via ACCKEYCONF.
*/ */
class AccLockReq { class AccLockReq {
friend class Dbtux;
friend class Dbacc; friend class Dbacc;
friend class Dbtup;
friend class Dbtux;
friend bool printACC_LOCKREQ(FILE *, const Uint32*, Uint32, Uint16); friend bool printACC_LOCKREQ(FILE *, const Uint32*, Uint32, Uint16);
public: public:
enum RequestType { // first byte enum RequestType { // first byte

View File

@ -46,7 +46,10 @@ private:
Uint32 requestInfo; Uint32 requestInfo;
Uint32 transId1; Uint32 transId1;
Uint32 transId2; Uint32 transId2;
union {
Uint32 savePointId; Uint32 savePointId;
Uint32 gci;
};
/** /**
* Previously there where also a scan type * Previously there where also a scan type
@ -58,6 +61,12 @@ private:
static void setLockMode(Uint32 & requestInfo, Uint32 lockMode); static void setLockMode(Uint32 & requestInfo, Uint32 lockMode);
static void setReadCommittedFlag(Uint32 & requestInfo, Uint32 readCommitted); static void setReadCommittedFlag(Uint32 & requestInfo, Uint32 readCommitted);
static void setDescendingFlag(Uint32 & requestInfo, Uint32 descending); static void setDescendingFlag(Uint32 & requestInfo, Uint32 descending);
static Uint32 getNoDiskScanFlag(const Uint32 & requestInfo);
static void setNoDiskScanFlag(Uint32 & requestInfo, Uint32 nodisk);
static Uint32 getNRScanFlag(const Uint32 & requestInfo);
static void setNRScanFlag(Uint32 & requestInfo, Uint32 nr);
}; };
/** /**
@ -66,15 +75,19 @@ private:
* l = Lock Mode - 1 Bit 2 * l = Lock Mode - 1 Bit 2
* h = Read Committed - 1 Bit 5 * h = Read Committed - 1 Bit 5
* z = Descending (TUX) - 1 Bit 6 * z = Descending (TUX) - 1 Bit 6
* d = No disk scan - 1 Bit 7
* n = Node recovery scan - 1 Bit 8
* *
* 1111111111222222222233 * 1111111111222222222233
* 01234567890123456789012345678901 * 01234567890123456789012345678901
* l hz * l hzdn
*/ */
#define AS_LOCK_MODE_SHIFT (2) #define AS_LOCK_MODE_SHIFT (2)
#define AS_LOCK_MODE_MASK (1) #define AS_LOCK_MODE_MASK (1)
#define AS_READ_COMMITTED_SHIFT (5) #define AS_READ_COMMITTED_SHIFT (5)
#define AS_DESCENDING_SHIFT (6) #define AS_DESCENDING_SHIFT (6)
#define AS_NO_DISK_SCAN (7)
#define AS_NR_SCAN (8)
inline inline
Uint32 Uint32
@ -115,6 +128,32 @@ AccScanReq::setDescendingFlag(UintR & requestInfo, UintR val){
requestInfo |= (val << AS_DESCENDING_SHIFT); requestInfo |= (val << AS_DESCENDING_SHIFT);
} }
inline
Uint32
AccScanReq::getNoDiskScanFlag(const Uint32 & requestInfo){
return (requestInfo >> AS_NO_DISK_SCAN) & 1;
}
inline
void
AccScanReq::setNoDiskScanFlag(UintR & requestInfo, UintR val){
ASSERT_BOOL(val, "AccScanReq::setNoDiskScanFlag");
requestInfo |= (val << AS_NO_DISK_SCAN);
}
inline
Uint32
AccScanReq::getNRScanFlag(const Uint32 & requestInfo){
return (requestInfo >> AS_NR_SCAN) & 1;
}
inline
void
AccScanReq::setNRScanFlag(UintR & requestInfo, UintR val){
ASSERT_BOOL(val, "AccScanReq::setNoDiskScanFlag");
requestInfo |= (val << AS_NR_SCAN);
}
class AccScanConf { class AccScanConf {
/** /**
* Sender(s) * Sender(s)

View File

@ -30,7 +30,7 @@ class CopyFragReq {
*/ */
friend class Dblqh; friend class Dblqh;
public: public:
STATIC_CONST( SignalLength = 7 ); STATIC_CONST( SignalLength = 8 );
private: private:
Uint32 userPtr; Uint32 userPtr;
@ -40,6 +40,7 @@ private:
Uint32 nodeId; Uint32 nodeId;
Uint32 schemaVersion; Uint32 schemaVersion;
Uint32 distributionKey; Uint32 distributionKey;
Uint32 gci;
}; };
class CopyFragConf { class CopyFragConf {

View File

@ -68,9 +68,9 @@ struct CreateFilegroupImplRef {
enum ErrorCode { enum ErrorCode {
NoError = 0, NoError = 0,
FilegroupAlreadyExists = 1, FilegroupAlreadyExists = 1502,
OutOfFilegroupRecords = 2, OutOfFilegroupRecords = 1503,
OutOfLogBufferMemory = 3 OutOfLogBufferMemory = 1504
}; };
Uint32 senderData; Uint32 senderData;
@ -155,15 +155,15 @@ struct CreateFileImplRef {
enum ErrorCode { enum ErrorCode {
NoError = 0, NoError = 0,
InvalidFilegroup = 1, InvalidFilegroup = 1505,
InvalidFilegroupVersion = 2, InvalidFilegroupVersion = 1506,
FileNoAlreadyExists = 3, FileNoAlreadyExists = 1507,
OutOfFileRecords = 4, OutOfFileRecords = 1508,
FileError = 5, FileError = 1509,
InvalidFileMetadata = 6, InvalidFileMetadata = 1510,
OutOfMemory = 7, OutOfMemory = 1511,
FileReadError = 8, FileReadError = 1512,
FilegroupNotOnline = 9 FilegroupNotOnline = 1513
}; };
Uint32 senderData; Uint32 senderData;

View File

@ -122,6 +122,10 @@ public:
FragmentData = 130, // CREATE_FRAGMENTATION reply FragmentData = 130, // CREATE_FRAGMENTATION reply
TablespaceId = 131, TablespaceId = 131,
TablespaceVersion = 132, TablespaceVersion = 132,
RowGCIFlag = 150,
RowChecksumFlag = 151,
TableEnd = 999, TableEnd = 999,
AttributeName = 1000, // String, Mandatory AttributeName = 1000, // String, Mandatory
@ -300,6 +304,9 @@ public:
Uint32 FragmentDataLen; Uint32 FragmentDataLen;
Uint16 FragmentData[(MAX_FRAGMENT_DATA_BYTES+1)/2]; Uint16 FragmentData[(MAX_FRAGMENT_DATA_BYTES+1)/2];
Uint32 RowGCIFlag;
Uint32 RowChecksumFlag;
void init(); void init();
}; };
@ -609,7 +616,9 @@ struct DictFilegroupInfo {
LF_UndoGrowSizeHi = 2001, LF_UndoGrowSizeHi = 2001,
LF_UndoGrowSizeLo = 2002, LF_UndoGrowSizeLo = 2002,
LF_UndoGrowPattern = 2003, LF_UndoGrowPattern = 2003,
LF_UndoGrowMaxSize = 2004 LF_UndoGrowMaxSize = 2004,
LF_UndoFreeWordsHi = 2006,
LF_UndoFreeWordsLo = 2007
}; };
// FragmentType constants // FragmentType constants
@ -645,6 +654,8 @@ struct DictFilegroupInfo {
GrowSpec LF_UndoGrow; GrowSpec LF_UndoGrow;
}; };
//GrowSpec LF_RedoGrow; //GrowSpec LF_RedoGrow;
Uint32 LF_UndoFreeWordsHi;
Uint32 LF_UndoFreeWordsLo;
void init(); void init();
}; };
static const Uint32 MappingSize; static const Uint32 MappingSize;

View File

@ -69,7 +69,8 @@ private:
ZSEND_END_TO = 41, ZSEND_END_TO = 41,
WAIT_DROP_TAB_WRITING_TO_FILE = 42, WAIT_DROP_TAB_WRITING_TO_FILE = 42,
CHECK_WAIT_DROP_TAB_FAILED_LQH = 43 CHECK_WAIT_DROP_TAB_FAILED_LQH = 43,
ZTO_START_FRAGMENTS = 44
}; };
}; };

View File

@ -112,10 +112,14 @@ public:
public: public:
Uint32 senderData; Uint32 senderData;
Uint32 tableId; Uint32 tableId;
union {
Uint32 gci; // For table Uint32 gci; // For table
Uint32 freeWordsHi; // for logfile group m_free_file_words
};
union { union {
Uint32 totalLen; // In words Uint32 totalLen; // In words
Uint32 freeExtents; Uint32 freeExtents;
Uint32 freeWordsLo; // for logfile group m_free_file_words
}; };
Uint32 tableType; Uint32 tableType;
Uint32 senderRef; Uint32 senderRef;

View File

@ -33,7 +33,7 @@ class AddFragReq {
friend bool printADD_FRAG_REQ(FILE *, const Uint32 *, Uint32, Uint16); friend bool printADD_FRAG_REQ(FILE *, const Uint32 *, Uint32, Uint16);
public: public:
STATIC_CONST( SignalLength = 9 ); STATIC_CONST( SignalLength = 10 );
enum RequestInfo { enum RequestInfo {
CreateInRunning = 0x8000000, CreateInRunning = 0x8000000,
@ -49,6 +49,7 @@ private:
Uint32 nodeId; Uint32 nodeId;
Uint32 totalFragments; Uint32 totalFragments;
Uint32 startGci; Uint32 startGci;
Uint32 logPartId;
}; };
class AddFragRef { class AddFragRef {
@ -104,7 +105,7 @@ class LqhFragReq {
friend bool printLQH_FRAG_REQ(FILE *, const Uint32 *, Uint32, Uint16); friend bool printLQH_FRAG_REQ(FILE *, const Uint32 *, Uint32, Uint16);
public: public:
STATIC_CONST( SignalLength = 19 ); STATIC_CONST( SignalLength = 20 );
enum RequestInfo { enum RequestInfo {
CreateInRunning = 0x8000000, CreateInRunning = 0x8000000,
@ -137,6 +138,7 @@ private:
Uint16 noOfKeyAttr; Uint16 noOfKeyAttr;
Uint8 checksumIndicator; Uint8 checksumIndicator;
Uint8 GCPIndicator; Uint8 GCPIndicator;
Uint32 logPartId;
}; };
class LqhFragConf { class LqhFragConf {

View File

@ -127,6 +127,18 @@ private:
static void setApplicationAddressFlag(UintR & requestInfo, UintR val); static void setApplicationAddressFlag(UintR & requestInfo, UintR val);
static void setMarkerFlag(UintR & requestInfo, UintR val); static void setMarkerFlag(UintR & requestInfo, UintR val);
static void setNoDiskFlag(UintR & requestInfo, UintR val); static void setNoDiskFlag(UintR & requestInfo, UintR val);
static UintR getRowidFlag(const UintR & requestInfo);
static void setRowidFlag(UintR & requestInfo, UintR val);
/**
* When doing DIRTY WRITES
*/
static UintR getGCIFlag(const UintR & requestInfo);
static void setGCIFlag(UintR & requestInfo, UintR val);
static UintR getNrCopyFlag(const UintR & requestInfo);
static void setNrCopyFlag(UintR & requestInfo, UintR val);
}; };
/** /**
@ -134,6 +146,8 @@ private:
* *
* k = Key len - 10 Bits (0-9) max 1023 * k = Key len - 10 Bits (0-9) max 1023
* l = Last Replica No - 2 Bits -> Max 3 (10-11) * l = Last Replica No - 2 Bits -> Max 3 (10-11)
IF version < NDBD_ROWID_VERSION
* t = Lock type - 3 Bits -> Max 7 (12-14) * t = Lock type - 3 Bits -> Max 7 (12-14)
* p = Application Addr. Ind - 1 Bit (15) * p = Application Addr. Ind - 1 Bit (15)
* d = Dirty indicator - 1 Bit (16) * d = Dirty indicator - 1 Bit (16)
@ -146,11 +160,14 @@ private:
* u = Read Len Return Ind - 1 Bit (28) * u = Read Len Return Ind - 1 Bit (28)
* m = Commit ack marker - 1 Bit (29) * m = Commit ack marker - 1 Bit (29)
* x = No disk usage - 1 Bit (30) * x = No disk usage - 1 Bit (30)
* - = Unused - 2 Bit (31) * z = Use rowid for insert - 1 Bit (31)
* * g = gci flag - 1 Bit (12)
* n = NR copy - 1 Bit (13)
* 1111111111222222222233 * 1111111111222222222233
* 01234567890123456789012345678901 * 01234567890123456789012345678901
* kkkkkkkkkklltttpdisooorraaacumx- * kkkkkkkkkklltttpdisooorraaacumxz
* kkkkkkkkkkllgn pdisooorraaacumxz
*/ */
#define RI_KEYLEN_SHIFT (0) #define RI_KEYLEN_SHIFT (0)
@ -173,6 +190,9 @@ private:
#define RI_RETURN_AI_SHIFT (28) #define RI_RETURN_AI_SHIFT (28)
#define RI_MARKER_SHIFT (29) #define RI_MARKER_SHIFT (29)
#define RI_NODISK_SHIFT (30) #define RI_NODISK_SHIFT (30)
#define RI_ROWID_SHIFT (31)
#define RI_GCI_SHIFT (12)
#define RI_NR_COPY_SHIFT (13)
/** /**
* Scan Info * Scan Info
@ -482,6 +502,45 @@ LqhKeyReq::getNoDiskFlag(const UintR & requestInfo){
return (requestInfo >> RI_NODISK_SHIFT) & 1; return (requestInfo >> RI_NODISK_SHIFT) & 1;
} }
inline
void
LqhKeyReq::setRowidFlag(UintR & requestInfo, UintR val){
ASSERT_BOOL(val, "LqhKeyReq::setRowidFlag");
requestInfo |= (val << RI_ROWID_SHIFT);
}
inline
UintR
LqhKeyReq::getRowidFlag(const UintR & requestInfo){
return (requestInfo >> RI_ROWID_SHIFT) & 1;
}
inline
void
LqhKeyReq::setGCIFlag(UintR & requestInfo, UintR val){
ASSERT_BOOL(val, "LqhKeyReq::setGciFlag");
requestInfo |= (val << RI_GCI_SHIFT);
}
inline
UintR
LqhKeyReq::getGCIFlag(const UintR & requestInfo){
return (requestInfo >> RI_GCI_SHIFT) & 1;
}
inline
void
LqhKeyReq::setNrCopyFlag(UintR & requestInfo, UintR val){
ASSERT_BOOL(val, "LqhKeyReq::setNrCopyFlag");
requestInfo |= (val << RI_NR_COPY_SHIFT);
}
inline
UintR
LqhKeyReq::getNrCopyFlag(const UintR & requestInfo){
return (requestInfo >> RI_NR_COPY_SHIFT) & 1;
}
class LqhKeyConf { class LqhKeyConf {
/** /**
* Reciver(s) * Reciver(s)

View File

@ -33,14 +33,6 @@ public:
ZSCAN_CLOSE = 6, ZSCAN_CLOSE = 6,
ZSCAN_NEXT_ABORT = 12 ZSCAN_NEXT_ABORT = 12
}; };
enum CopyFlag {
todo_ZCOPY_NEXT = 1,
todo_ZCOPY_NEXT_COMMIT = 2,
todo_ZCOPY_COMMIT = 3,
todo_ZCOPY_REPEAT = 4,
todo_ZCOPY_ABORT = 5,
todo_ZCOPY_CLOSE = 6
};
STATIC_CONST( SignalLength = 3 ); STATIC_CONST( SignalLength = 3 );
private: private:
Uint32 accPtr; // scan record in ACC/TUX Uint32 accPtr; // scan record in ACC/TUX
@ -62,8 +54,7 @@ private:
Uint32 fragId; Uint32 fragId;
Uint32 localKey[2]; Uint32 localKey[2];
Uint32 localKeyLength; Uint32 localKeyLength;
Uint32 keyLength; Uint32 gci;
Uint32 key[4];
}; };
#endif #endif

View File

@ -36,7 +36,7 @@ class TupKeyReq {
friend bool printTUPKEYREQ(FILE * output, const Uint32 * theData, Uint32 len, Uint16 receiverBlockNo); friend bool printTUPKEYREQ(FILE * output, const Uint32 * theData, Uint32 len, Uint16 receiverBlockNo);
public: public:
STATIC_CONST( SignalLength = 16 ); STATIC_CONST( SignalLength = 18 );
private: private:
@ -59,6 +59,8 @@ private:
Uint32 tcOpIndex; Uint32 tcOpIndex;
Uint32 savePointId; Uint32 savePointId;
Uint32 disk_page; Uint32 disk_page;
Uint32 m_row_id_page_no;
Uint32 m_row_id_page_idx;
}; };
class TupKeyConf { class TupKeyConf {
@ -78,7 +80,7 @@ class TupKeyConf {
friend bool printTUPKEYCONF(FILE * output, const Uint32 * theData, Uint32 len, Uint16 receiverBlockNo); friend bool printTUPKEYCONF(FILE * output, const Uint32 * theData, Uint32 len, Uint16 receiverBlockNo);
public: public:
STATIC_CONST( SignalLength = 5 ); STATIC_CONST( SignalLength = 6 );
private: private:
@ -90,6 +92,7 @@ private:
Uint32 writeLength; Uint32 writeLength;
Uint32 noFiredTriggers; Uint32 noFiredTriggers;
Uint32 lastRow; Uint32 lastRow;
Uint32 rowid;
}; };
class TupKeyRef { class TupKeyRef {

View File

@ -57,6 +57,10 @@ char ndb_version_string_buf[NDB_VERSION_STRING_BUF_SZ];
*/ */
/*#define NDB_VERSION_ID 0*/ /*#define NDB_VERSION_ID 0*/
/**
* From which version do we support rowid
*/
#define NDBD_ROWID_VERSION (MAKE_VERSION(5,1,6))
#define NDBD_INCL_NODECONF_VERSION_4 MAKE_VERSION(4,1,17) #define NDBD_INCL_NODECONF_VERSION_4 MAKE_VERSION(4,1,17)
#define NDBD_INCL_NODECONF_VERSION_5 MAKE_VERSION(5,0,18) #define NDBD_INCL_NODECONF_VERSION_5 MAKE_VERSION(5,0,18)

View File

@ -94,6 +94,8 @@ public:
*/ */
virtual int getObjectVersion() const = 0; virtual int getObjectVersion() const = 0;
virtual int getObjectId() const = 0;
/** /**
* Object type * Object type
*/ */
@ -501,6 +503,8 @@ public:
static const Column * RANGE_NO; static const Column * RANGE_NO;
static const Column * DISK_REF; static const Column * DISK_REF;
static const Column * RECORDS_IN_RANGE; static const Column * RECORDS_IN_RANGE;
static const Column * ROWID;
static const Column * ROW_GCI;
int getSizeInBytes() const; int getSizeInBytes() const;
#endif #endif
@ -751,6 +755,7 @@ public:
void setTablespace(const char * name); void setTablespace(const char * name);
void setTablespace(const class Tablespace &); void setTablespace(const class Tablespace &);
const char * getTablespace() const; const char * getTablespace() const;
Uint32 getTablespaceId() const;
/** /**
* Get table object type * Get table object type
@ -767,6 +772,11 @@ public:
*/ */
virtual int getObjectVersion() const; virtual int getObjectVersion() const;
/**
* Get object id
*/
virtual int getObjectId() const;
/** /**
* Set frm file to store with this table * Set frm file to store with this table
*/ */
@ -784,6 +794,15 @@ public:
/** @} *******************************************************************/ /** @} *******************************************************************/
/**
*
*/
void setRowGCIIndicator(bool value);
bool getRowGCIIndicator() const;
void setRowChecksumIndicator(bool value);
bool getRowChecksumIndicator() const;
#ifndef DOXYGEN_SHOULD_SKIP_INTERNAL #ifndef DOXYGEN_SHOULD_SKIP_INTERNAL
const char *getMysqlName() const; const char *getMysqlName() const;
@ -887,6 +906,11 @@ public:
*/ */
virtual int getObjectVersion() const; virtual int getObjectVersion() const;
/**
* Get object id
*/
virtual int getObjectId() const;
/** @} *******************************************************************/ /** @} *******************************************************************/
/** /**
@ -1157,6 +1181,11 @@ public:
*/ */
virtual int getObjectVersion() const; virtual int getObjectVersion() const;
/**
* Get object id
*/
virtual int getObjectId() const;
#ifndef DOXYGEN_SHOULD_SKIP_INTERNAL #ifndef DOXYGEN_SHOULD_SKIP_INTERNAL
void print(); void print();
#endif #endif
@ -1183,6 +1212,7 @@ public:
class LogfileGroup : public Object { class LogfileGroup : public Object {
public: public:
LogfileGroup(); LogfileGroup();
LogfileGroup(const LogfileGroup&);
virtual ~LogfileGroup(); virtual ~LogfileGroup();
void setName(const char * name); void setName(const char * name);
@ -1194,6 +1224,8 @@ public:
void setAutoGrowSpecification(const AutoGrowSpecification&); void setAutoGrowSpecification(const AutoGrowSpecification&);
const AutoGrowSpecification& getAutoGrowSpecification() const; const AutoGrowSpecification& getAutoGrowSpecification() const;
Uint64 getUndoFreeWords() const;
/** /**
* Get object status * Get object status
*/ */
@ -1204,6 +1236,11 @@ public:
*/ */
virtual int getObjectVersion() const; virtual int getObjectVersion() const;
/**
* Get object id
*/
virtual int getObjectId() const;
private: private:
friend class NdbDictionaryImpl; friend class NdbDictionaryImpl;
friend class NdbLogfileGroupImpl; friend class NdbLogfileGroupImpl;
@ -1217,6 +1254,7 @@ public:
class Tablespace : public Object { class Tablespace : public Object {
public: public:
Tablespace(); Tablespace();
Tablespace(const Tablespace&);
virtual ~Tablespace(); virtual ~Tablespace();
void setName(const char * name); void setName(const char * name);
@ -1230,7 +1268,9 @@ public:
void setDefaultLogfileGroup(const char * name); void setDefaultLogfileGroup(const char * name);
void setDefaultLogfileGroup(const class LogfileGroup&); void setDefaultLogfileGroup(const class LogfileGroup&);
const char * getDefaultLogfileGroup() const; const char * getDefaultLogfileGroup() const;
Uint32 getDefaultLogfileGroupId() const;
/** /**
* Get object status * Get object status
@ -1242,6 +1282,11 @@ public:
*/ */
virtual int getObjectVersion() const; virtual int getObjectVersion() const;
/**
* Get object id
*/
virtual int getObjectId() const;
private: private:
friend class NdbTablespaceImpl; friend class NdbTablespaceImpl;
class NdbTablespaceImpl & m_impl; class NdbTablespaceImpl & m_impl;
@ -1251,6 +1296,7 @@ public:
class Datafile : public Object { class Datafile : public Object {
public: public:
Datafile(); Datafile();
Datafile(const Datafile&);
virtual ~Datafile(); virtual ~Datafile();
void setPath(const char * name); void setPath(const char * name);
@ -1263,6 +1309,7 @@ public:
void setTablespace(const char * name); void setTablespace(const char * name);
void setTablespace(const class Tablespace &); void setTablespace(const class Tablespace &);
const char * getTablespace() const; const char * getTablespace() const;
Uint32 getTablespaceId() const;
void setNode(Uint32 nodeId); void setNode(Uint32 nodeId);
Uint32 getNode() const; Uint32 getNode() const;
@ -1279,6 +1326,11 @@ public:
*/ */
virtual int getObjectVersion() const; virtual int getObjectVersion() const;
/**
* Get object id
*/
virtual int getObjectId() const;
private: private:
friend class NdbDatafileImpl; friend class NdbDatafileImpl;
class NdbDatafileImpl & m_impl; class NdbDatafileImpl & m_impl;
@ -1288,6 +1340,7 @@ public:
class Undofile : public Object { class Undofile : public Object {
public: public:
Undofile(); Undofile();
Undofile(const Undofile&);
virtual ~Undofile(); virtual ~Undofile();
void setPath(const char * path); void setPath(const char * path);
@ -1295,11 +1348,11 @@ public:
void setSize(Uint64); void setSize(Uint64);
Uint64 getSize() const; Uint64 getSize() const;
Uint64 getFree() const;
void setLogfileGroup(const char * name); void setLogfileGroup(const char * name);
void setLogfileGroup(const class LogfileGroup &); void setLogfileGroup(const class LogfileGroup &);
const char * getLogfileGroup() const; const char * getLogfileGroup() const;
Uint32 getLogfileGroupId() const;
void setNode(Uint32 nodeId); void setNode(Uint32 nodeId);
Uint32 getNode() const; Uint32 getNode() const;
@ -1316,6 +1369,11 @@ public:
*/ */
virtual int getObjectVersion() const; virtual int getObjectVersion() const;
/**
* Get object id
*/
virtual int getObjectId() const;
private: private:
friend class NdbUndofileImpl; friend class NdbUndofileImpl;
class NdbUndofileImpl & m_impl; class NdbUndofileImpl & m_impl;

View File

@ -18,6 +18,19 @@
#ifndef CLUSTER_CONNECTION_HPP #ifndef CLUSTER_CONNECTION_HPP
#define CLUSTER_CONNECTION_HPP #define CLUSTER_CONNECTION_HPP
class Ndb_cluster_connection_node_iter
{
friend class Ndb_cluster_connection_impl;
public:
Ndb_cluster_connection_node_iter() : scan_state(~0),
init_pos(0),
cur_pos(0) {};
private:
unsigned char scan_state;
unsigned char init_pos;
unsigned char cur_pos;
};
/** /**
* @class Ndb_cluster_connection * @class Ndb_cluster_connection
* @brief Represents a connection to a cluster of storage nodes. * @brief Represents a connection to a cluster of storage nodes.
@ -88,6 +101,9 @@ public:
unsigned no_db_nodes(); unsigned no_db_nodes();
unsigned node_id(); unsigned node_id();
void init_get_next_node(Ndb_cluster_connection_node_iter &iter);
unsigned int get_next_node(Ndb_cluster_connection_node_iter &iter);
#endif #endif
private: private:

View File

@ -47,6 +47,11 @@ public:
*/ */
static void set(unsigned size, Uint32 data[]); static void set(unsigned size, Uint32 data[]);
/**
* set bit from <em>start</em> to <em>last</em>
*/
static void set_range(unsigned size, Uint32 data[], unsigned start, unsigned last);
/** /**
* assign - Set all bits in <em>dst</em> to corresponding in <em>src/<em> * assign - Set all bits in <em>dst</em> to corresponding in <em>src/<em>
*/ */
@ -62,6 +67,11 @@ public:
*/ */
static void clear(unsigned size, Uint32 data[]); static void clear(unsigned size, Uint32 data[]);
/**
* clear bit from <em>start</em> to <em>last</em>
*/
static void clear_range(unsigned size, Uint32 data[], unsigned start, unsigned last);
static Uint32 getWord(unsigned size, Uint32 data[], unsigned word_pos); static Uint32 getWord(unsigned size, Uint32 data[], unsigned word_pos);
static void setWord(unsigned size, Uint32 data[], static void setWord(unsigned size, Uint32 data[],
unsigned word_pos, Uint32 new_word); unsigned word_pos, Uint32 new_word);
@ -184,6 +194,34 @@ BitmaskImpl::set(unsigned size, Uint32 data[])
} }
} }
inline void
BitmaskImpl::set_range(unsigned size, Uint32 data[],
unsigned start, unsigned last)
{
Uint32 *ptr = data + (start >> 5);
Uint32 *end = data + (last >> 5);
assert(start <= last);
assert(last < (size << 5));
Uint32 tmp_word = ~(Uint32)0 << (start & 31);
if (ptr < end)
{
* ptr ++ |= tmp_word;
for(; ptr < end; )
{
* ptr ++ = ~(Uint32)0;
}
tmp_word = ~(Uint32)0;
}
tmp_word &= ~(~(Uint32)0 << (last & 31));
* ptr |= tmp_word;
}
inline void inline void
BitmaskImpl::assign(unsigned size, Uint32 dst[], const Uint32 src[]) BitmaskImpl::assign(unsigned size, Uint32 dst[], const Uint32 src[])
{ {
@ -207,6 +245,34 @@ BitmaskImpl::clear(unsigned size, Uint32 data[])
} }
} }
inline void
BitmaskImpl::clear_range(unsigned size, Uint32 data[],
unsigned start, unsigned last)
{
Uint32 *ptr = data + (start >> 5);
Uint32 *end = data + (last >> 5);
assert(start <= last);
assert(last < (size << 5));
Uint32 tmp_word = ~(Uint32)0 << (start & 31);
if (ptr < end)
{
* ptr ++ &= ~tmp_word;
for(; ptr < end; )
{
* ptr ++ = 0;
}
tmp_word = ~(Uint32)0;
}
tmp_word &= ~(~(Uint32)0 << (last & 31));
* ptr &= ~tmp_word;
}
inline inline
Uint32 Uint32
BitmaskImpl::getWord(unsigned size, Uint32 data[], unsigned word_pos) BitmaskImpl::getWord(unsigned size, Uint32 data[], unsigned word_pos)

View File

@ -31,6 +31,8 @@ public:
unsigned size() const { return m_size; }; unsigned size() const { return m_size; };
void push_back(const T &); void push_back(const T &);
void push(const T&, unsigned pos);
T& set(T&, unsigned pos, T& fill_obj);
T& back(); T& back();
void erase(unsigned index); void erase(unsigned index);
@ -104,6 +106,31 @@ Vector<T>::push_back(const T & t){
m_size++; m_size++;
} }
template<class T>
void
Vector<T>::push(const T & t, unsigned pos)
{
push_back(t);
if (pos < m_size - 1)
{
for(unsigned i = m_size - 1; i > pos; i--)
{
m_items[i] = m_items[i-1];
}
m_items[pos] = t;
}
}
template<class T>
T&
Vector<T>::set(T & t, unsigned pos, T& fill_obj)
{
fill(pos, fill_obj);
T& ret = m_items[pos];
m_items[pos] = t;
return ret;
}
template<class T> template<class T>
void void
Vector<T>::erase(unsigned i){ Vector<T>::erase(unsigned i){

View File

@ -49,6 +49,8 @@ DictTabInfo::TableMapping[] = {
DTIMAPB(Table, FragmentData, FragmentData, 0, MAX_FRAGMENT_DATA_BYTES, FragmentDataLen), DTIMAPB(Table, FragmentData, FragmentData, 0, MAX_FRAGMENT_DATA_BYTES, FragmentDataLen),
DTIMAP(Table, TablespaceId, TablespaceId), DTIMAP(Table, TablespaceId, TablespaceId),
DTIMAP(Table, TablespaceVersion, TablespaceVersion), DTIMAP(Table, TablespaceVersion, TablespaceVersion),
DTIMAP(Table, RowGCIFlag, RowGCIFlag),
DTIMAP(Table, RowChecksumFlag, RowChecksumFlag),
DTIBREAK(AttributeName) DTIBREAK(AttributeName)
}; };
@ -128,6 +130,9 @@ DictTabInfo::Table::init(){
memset(FragmentData, 0, sizeof(FragmentData)); memset(FragmentData, 0, sizeof(FragmentData));
TablespaceId = RNIL; TablespaceId = RNIL;
TablespaceVersion = ~0; TablespaceVersion = ~0;
RowGCIFlag = ~0;
RowChecksumFlag = ~0;
} }
void void
@ -174,6 +179,8 @@ DictFilegroupInfo::Mapping[] = {
DFGIMAP(Filegroup, LF_UndoGrowSizeLo, LF_UndoGrow.GrowSizeLo), DFGIMAP(Filegroup, LF_UndoGrowSizeLo, LF_UndoGrow.GrowSizeLo),
DFGIMAPS(Filegroup, LF_UndoGrowPattern, LF_UndoGrow.GrowPattern, 0,PATH_MAX), DFGIMAPS(Filegroup, LF_UndoGrowPattern, LF_UndoGrow.GrowPattern, 0,PATH_MAX),
DFGIMAP(Filegroup, LF_UndoGrowMaxSize, LF_UndoGrow.GrowMaxSize), DFGIMAP(Filegroup, LF_UndoGrowMaxSize, LF_UndoGrow.GrowMaxSize),
DFGIMAP(Filegroup, LF_UndoFreeWordsHi, LF_UndoFreeWordsHi),
DFGIMAP(Filegroup, LF_UndoFreeWordsLo, LF_UndoFreeWordsLo),
DFGIBREAK(FileName) DFGIBREAK(FileName)
}; };

View File

@ -36,5 +36,6 @@ printFSCLOSEREQ(FILE * output, const Uint32 * theData, Uint32 len, Uint16 receiv
else else
fprintf(output, "Don't remove file"); fprintf(output, "Don't remove file");
fprintf(output, "\n"); fprintf(output, "\n");
return true;
return len == 4;
} }

View File

@ -51,6 +51,12 @@ printLQHKEYREQ(FILE * output, const Uint32 * theData, Uint32 len, Uint16 receive
fprintf(output, "CommitAckMarker "); fprintf(output, "CommitAckMarker ");
if(LqhKeyReq::getNoDiskFlag(reqInfo)) if(LqhKeyReq::getNoDiskFlag(reqInfo))
fprintf(output, "NoDisk "); fprintf(output, "NoDisk ");
if(LqhKeyReq::getRowidFlag(reqInfo))
fprintf(output, "Rowid ");
if(LqhKeyReq::getNrCopyFlag(reqInfo))
fprintf(output, "NrCopy ");
if(LqhKeyReq::getGCIFlag(reqInfo))
fprintf(output, "GCI ");
fprintf(output, "ScanInfo/noFiredTriggers: H\'%x\n", sig->scanInfo); fprintf(output, "ScanInfo/noFiredTriggers: H\'%x\n", sig->scanInfo);
@ -120,6 +126,20 @@ printLQHKEYREQ(FILE * output, const Uint32 * theData, Uint32 len, Uint16 receive
fprintf(output, "\n"); fprintf(output, "\n");
} }
if (LqhKeyReq::getRowidFlag(reqInfo))
{
fprintf(output, " Rowid: [ page: %d idx: %d ]\n",
sig->variableData[nextPos + 0],
sig->variableData[nextPos + 1]);
nextPos += 2;
}
if (LqhKeyReq::getGCIFlag(reqInfo))
{
fprintf(output, " GCI: %u", sig->variableData[nextPos + 0]);
nextPos++;
}
if(!LqhKeyReq::getInterpretedFlag(reqInfo)){ if(!LqhKeyReq::getInterpretedFlag(reqInfo)){
fprintf(output, " AttrInfo: "); fprintf(output, " AttrInfo: ");
for(int i = 0; i<LqhKeyReq::getAIInLqhKeyReq(reqInfo); i++, nextPos++) for(int i = 0; i<LqhKeyReq::getAIInLqhKeyReq(reqInfo); i++, nextPos++)

View File

@ -363,10 +363,6 @@ const GsnName SignalNames [] = {
,{ GSN_EVENT_SUBSCRIBE_REQ, "EVENT_SUBSCRIBE_REQ" } ,{ GSN_EVENT_SUBSCRIBE_REQ, "EVENT_SUBSCRIBE_REQ" }
,{ GSN_EVENT_SUBSCRIBE_CONF, "EVENT_SUBSCRIBE_CONF" } ,{ GSN_EVENT_SUBSCRIBE_CONF, "EVENT_SUBSCRIBE_CONF" }
,{ GSN_EVENT_SUBSCRIBE_REF, "EVENT_SUBSCRIBE_REF" } ,{ GSN_EVENT_SUBSCRIBE_REF, "EVENT_SUBSCRIBE_REF" }
,{ GSN_ACC_COM_BLOCK, "ACC_COM_BLOCK" }
,{ GSN_ACC_COM_UNBLOCK, "ACC_COM_UNBLOCK" }
,{ GSN_TUP_COM_BLOCK, "TUP_COM_BLOCK" }
,{ GSN_TUP_COM_UNBLOCK, "TUP_COM_UNBLOCK" }
,{ GSN_DUMP_STATE_ORD, "DUMP_STATE_ORD" } ,{ GSN_DUMP_STATE_ORD, "DUMP_STATE_ORD" }
,{ GSN_START_INFOREQ, "START_INFOREQ" } ,{ GSN_START_INFOREQ, "START_INFOREQ" }

View File

@ -16,8 +16,6 @@ void print(const Uint32 src[], Uint32 len, Uint32 pos = 0)
} }
} }
#ifndef __TEST_BITMASK__
void void
BitmaskImpl::getFieldImpl(const Uint32 src[], BitmaskImpl::getFieldImpl(const Uint32 src[],
unsigned shiftL, unsigned len, Uint32 dst[]) unsigned shiftL, unsigned len, Uint32 dst[])
@ -78,7 +76,7 @@ BitmaskImpl::setFieldImpl(Uint32 dst[],
* dst |= ((* src) & ((1 << (len - shiftR)) - 1)) << shiftR ; * dst |= ((* src) & ((1 << (len - shiftR)) - 1)) << shiftR ;
} }
} }
#else #ifdef __TEST_BITMASK__
#define DEBUG 0 #define DEBUG 0
#include <Vector.hpp> #include <Vector.hpp>
@ -342,6 +340,74 @@ do_test(int bitmask_size)
alloc_list.push_back(a); alloc_list.push_back(a);
} }
} }
for(Uint32 i = 0; i<1000; i++)
{
Uint32 sz32 = 10+rand() % 100;
Uint32 zero = 0;
Vector<Uint32> map;
map.fill(sz32, zero);
Uint32 sz = 32 * sz32;
Uint32 start = (rand() % sz);
Uint32 stop = start + ((rand() % (sz - start)) & 0xFFFFFFFF);
Vector<Uint32> check;
check.fill(sz32, zero);
for(Uint32 j = 0; j<sz; j++)
{
bool expect = (j >= start && j<stop);
if(expect)
BitmaskImpl::set(sz32, check.getBase(), j);
}
BitmaskImpl::set(sz32, map.getBase(), start, stop);
if (!BitmaskImpl::equal(sz32, map.getBase(), check.getBase()))
{
ndbout_c(" FAIL sz: %d [ %d %d ]", sz, start, stop);
printf("check: ");
for(Uint32 j = 0; j<sz32; j++)
printf("%.8x ", check[j]);
printf("\n");
printf("map : ");
for(Uint32 j = 0; j<sz32; j++)
printf("%.8x ", map[j]);
printf("\n");
abort();
}
map.clear();
check.clear();
Uint32 one = ~(Uint32)0;
map.fill(sz32, one);
check.fill(sz32, one);
for(Uint32 j = 0; j<sz; j++)
{
bool expect = (j >= start && j<stop);
if(expect)
BitmaskImpl::clear(sz32, check.getBase(), j);
}
BitmaskImpl::clear(sz32, map.getBase(), start, stop);
if (!BitmaskImpl::equal(sz32, map.getBase(), check.getBase()))
{
ndbout_c(" FAIL sz: %d [ %d %d ]", sz, start, stop);
printf("check: ");
for(Uint32 j = 0; j<sz32; j++)
printf("%.8x ", check[j]);
printf("\n");
printf("map : ");
for(Uint32 j = 0; j<sz32; j++)
printf("%.8x ", map[j]);
printf("\n");
abort();
}
}
#endif #endif
} }

View File

@ -3,7 +3,7 @@ Next NDBCNTR 1000
Next NDBFS 2000 Next NDBFS 2000
Next DBACC 3002 Next DBACC 3002
Next DBTUP 4013 Next DBTUP 4013
Next DBLQH 5042 Next DBLQH 5043
Next DBDICT 6007 Next DBDICT 6007
Next DBDIH 7174 Next DBDIH 7174
Next DBTC 8037 Next DBTC 8037
@ -314,6 +314,8 @@ LQH:
5026 Crash when receiving COPY_ACTIVEREQ 5026 Crash when receiving COPY_ACTIVEREQ
5027 Crash when receiving STAT_RECREQ 5027 Crash when receiving STAT_RECREQ
5042 Crash starting node, when scan is finished on primary replica
Test Crashes in handling take over Test Crashes in handling take over
---------------------------------- ----------------------------------
@ -461,3 +463,13 @@ Dbdict:
6003 Crash in participant @ CreateTabReq::Prepare 6003 Crash in participant @ CreateTabReq::Prepare
6004 Crash in participant @ CreateTabReq::Commit 6004 Crash in participant @ CreateTabReq::Commit
6005 Crash in participant @ CreateTabReq::CreateDrop 6005 Crash in participant @ CreateTabReq::CreateDrop
Dbtup:
4014 - handleInsert - Out of undo buffer
4015 - handleInsert - Out of log space
4016 - handleInsert - AI Inconsistency
4017 - handleInsert - Out of memory
4018 - handleInsert - Null check error
4019 - handleInsert - Alloc rowid error
4020 - handleInsert - Size change error
4021 - handleInsert - Out of disk space

View File

@ -0,0 +1,49 @@
*** Copy thread
Scan rowids with GCP > starting nodes GCP
Cases for different ROWID combinations
RI Primary Starting Result
1 A A Update A
2 B B* Delete B* + Insert B
3 C C* Delete C* + Delete C + Insert C
C
4 Deleted D Delete D
5 E Deleted Insert E
6 F Deleted Delete F + Insert F
F
7 Deleted Deleted Update GCP
*** Ordinary operations
Op Starting Result
Insert A@1 A@1 Update A
Insert A@1 A@2 Delete A@2, Insert A@1
Insert A@1 1 busy, A@2 Delete 1, Delete A@2, Insert A@1
Insert A@1 1 busy Delete 1, Insert A@1
Delete A@1 A@1 Delete A@1
Delete A@1 else noop
Update A@1 A@1 Update A
Update A@1 else noop
***
Rationale:
If copy has passed rowid,
then no ordinary operation should be a noop
If copy has not passed,
then it's ok to do a noop as copy will get there sooner or later
Copy may not end up in lock queue, as no lock is held on primary.
therefore ordinary ops must be noops when rowid missmatch
When not scanning in rowid order (e.g. disk order) one must
1 make a second pass in rowid order
- finding deletes and inserts (as 2)
2 mark all inserts "earlier" than current scan pos
so they will be found during second pass
Note: Dealloc is performed first on backup then on primary

View File

@ -14,6 +14,7 @@
along with this program; if not, write to the Free Software along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
#include <my_config.h>
#include "Backup.hpp" #include "Backup.hpp"
#include <ndb_version.h> #include <ndb_version.h>
@ -2514,15 +2515,22 @@ Backup::execLIST_TABLES_CONF(Signal* signal)
Uint32 tableId = ListTablesConf::getTableId(conf->tableData[i]); Uint32 tableId = ListTablesConf::getTableId(conf->tableData[i]);
Uint32 tableType = ListTablesConf::getTableType(conf->tableData[i]); Uint32 tableType = ListTablesConf::getTableType(conf->tableData[i]);
Uint32 state= ListTablesConf::getTableState(conf->tableData[i]); Uint32 state= ListTablesConf::getTableState(conf->tableData[i]);
if (!DictTabInfo::isTable(tableType) && !DictTabInfo::isIndex(tableType)){
if (! (DictTabInfo::isTable(tableType) ||
DictTabInfo::isIndex(tableType) ||
DictTabInfo::isFilegroup(tableType) ||
DictTabInfo::isFile(tableType)))
{
jam(); jam();
continue; continue;
}//if }
if (state != DictTabInfo::StateOnline) if (state != DictTabInfo::StateOnline)
{ {
jam(); jam();
continue; continue;
}//if }
TablePtr tabPtr; TablePtr tabPtr;
ptr.p->tables.seize(tabPtr); ptr.p->tables.seize(tabPtr);
if(tabPtr.i == RNIL) { if(tabPtr.i == RNIL) {
@ -2832,6 +2840,8 @@ Backup::execGET_TABINFO_CONF(Signal* signal)
//const Uint32 senderRef = info->senderRef; //const Uint32 senderRef = info->senderRef;
const Uint32 len = conf->totalLen; const Uint32 len = conf->totalLen;
const Uint32 senderData = conf->senderData; const Uint32 senderData = conf->senderData;
const Uint32 tableType = conf->tableType;
const Uint32 tableId = conf->tableId;
BackupRecordPtr ptr; BackupRecordPtr ptr;
c_backupPool.getPtr(ptr, senderData); c_backupPool.getPtr(ptr, senderData);
@ -2840,6 +2850,9 @@ Backup::execGET_TABINFO_CONF(Signal* signal)
signal->getSection(dictTabInfoPtr, GetTabInfoConf::DICT_TAB_INFO); signal->getSection(dictTabInfoPtr, GetTabInfoConf::DICT_TAB_INFO);
ndbrequire(dictTabInfoPtr.sz == len); ndbrequire(dictTabInfoPtr.sz == len);
TablePtr tabPtr ;
ndbrequire(findTable(ptr, tabPtr, tableId));
/** /**
* No of pages needed * No of pages needed
*/ */
@ -2860,7 +2873,7 @@ Backup::execGET_TABINFO_CONF(Signal* signal)
ptr.p->files.getPtr(filePtr, ptr.p->ctlFilePtr); ptr.p->files.getPtr(filePtr, ptr.p->ctlFilePtr);
FsBuffer & buf = filePtr.p->operation.dataBuffer; FsBuffer & buf = filePtr.p->operation.dataBuffer;
{ // Write into ctl file { // Write into ctl file
Uint32* dst, dstLen = len + 2; Uint32* dst, dstLen = len + 3;
if(!buf.getWritePtr(&dst, dstLen)) { if(!buf.getWritePtr(&dst, dstLen)) {
jam(); jam();
ndbrequire(false); ndbrequire(false);
@ -2875,49 +2888,62 @@ Backup::execGET_TABINFO_CONF(Signal* signal)
BackupFormat::CtlFile::TableDescription * desc = BackupFormat::CtlFile::TableDescription * desc =
(BackupFormat::CtlFile::TableDescription*)dst; (BackupFormat::CtlFile::TableDescription*)dst;
desc->SectionType = htonl(BackupFormat::TABLE_DESCRIPTION); desc->SectionType = htonl(BackupFormat::TABLE_DESCRIPTION);
desc->SectionLength = htonl(len + 2); desc->SectionLength = htonl(len + 3);
dst += 2; desc->TableType = htonl(tableType);
dst += 3;
copy(dst, dictTabInfoPtr); copy(dst, dictTabInfoPtr);
buf.updateWritePtr(dstLen); buf.updateWritePtr(dstLen);
}//if }//if
} }
if(ptr.p->checkError()) {
jam();
releaseSections(signal);
defineBackupRef(signal, ptr);
return;
}//if
if (!DictTabInfo::isTable(tabPtr.p->tableType))
{
jam();
releaseSections(signal);
TablePtr tmp = tabPtr;
ptr.p->tables.next(tabPtr);
ptr.p->tables.release(tmp);
goto next;
}
ndbrequire(ptr.p->pages.getSize() >= noPages); ndbrequire(ptr.p->pages.getSize() >= noPages);
Page32Ptr pagePtr; Page32Ptr pagePtr;
ptr.p->pages.getPtr(pagePtr, 0); ptr.p->pages.getPtr(pagePtr, 0);
copy(&pagePtr.p->data[0], dictTabInfoPtr); copy(&pagePtr.p->data[0], dictTabInfoPtr);
releaseSections(signal); releaseSections(signal);
if(ptr.p->checkError()) { if (!parseTableDescription(signal, ptr, tabPtr, len))
jam();
defineBackupRef(signal, ptr);
return;
}//if
TablePtr tabPtr = parseTableDescription(signal, ptr, len);
if(tabPtr.i == RNIL) {
jam();
defineBackupRef(signal, ptr);
return;
}//if
TablePtr tmp = tabPtr;
ptr.p->tables.next(tabPtr);
if(DictTabInfo::isIndex(tmp.p->tableType))
{ {
jam(); jam();
ptr.p->tables.release(tmp); defineBackupRef(signal, ptr);
return;
} }
else if(!ptr.p->is_lcp())
if(!ptr.p->is_lcp())
{ {
jam(); jam();
signal->theData[0] = tmp.p->tableId; signal->theData[0] = tabPtr.p->tableId;
signal->theData[1] = 1; // lock signal->theData[1] = 1; // lock
EXECUTE_DIRECT(DBDICT, GSN_BACKUP_FRAGMENT_REQ, signal, 2); EXECUTE_DIRECT(DBDICT, GSN_BACKUP_FRAGMENT_REQ, signal, 2);
} }
if(tabPtr.i == RNIL) { ptr.p->tables.next(tabPtr);
next:
if(tabPtr.i == RNIL)
{
/**
* Done with all tables...
*/
jam(); jam();
ptr.p->pages.release(); ptr.p->pages.release();
@ -2936,6 +2962,9 @@ Backup::execGET_TABINFO_CONF(Signal* signal)
return; return;
}//if }//if
/**
* Fetch next table...
*/
signal->theData[0] = BackupContinueB::BUFFER_FULL_META; signal->theData[0] = BackupContinueB::BUFFER_FULL_META;
signal->theData[1] = ptr.i; signal->theData[1] = ptr.i;
signal->theData[2] = tabPtr.i; signal->theData[2] = tabPtr.i;
@ -2943,8 +2972,11 @@ Backup::execGET_TABINFO_CONF(Signal* signal)
return; return;
} }
Backup::TablePtr bool
Backup::parseTableDescription(Signal* signal, BackupRecordPtr ptr, Uint32 len) Backup::parseTableDescription(Signal* signal,
BackupRecordPtr ptr,
TablePtr tabPtr,
Uint32 len)
{ {
Page32Ptr pagePtr; Page32Ptr pagePtr;
@ -2962,17 +2994,14 @@ Backup::parseTableDescription(Signal* signal, BackupRecordPtr ptr, Uint32 len)
true, true); true, true);
ndbrequire(stat == SimpleProperties::Break); ndbrequire(stat == SimpleProperties::Break);
TablePtr tabPtr; bool lcp = ptr.p->is_lcp();
ndbrequire(findTable(ptr, tabPtr, tmpTab.TableId));
if(DictTabInfo::isIndex(tabPtr.p->tableType)){ ndbrequire(tabPtr.p->tableId == tmpTab.TableId);
jam(); ndbrequire(lcp || (tabPtr.p->tableType == tmpTab.TableType));
return tabPtr;
}
/** /**
* LCP should not save disk attributes but only mem attributes * LCP should not save disk attributes but only mem attributes
*/ */
bool lcp = ptr.p->is_lcp();
/** /**
* Initialize table object * Initialize table object
@ -3017,8 +3046,7 @@ Backup::parseTableDescription(Signal* signal, BackupRecordPtr ptr, Uint32 len)
{ {
jam(); jam();
ptr.p->setErrorCode(DefineBackupRef::FailedToAllocateAttributeRecord); ptr.p->setErrorCode(DefineBackupRef::FailedToAllocateAttributeRecord);
tabPtr.i = RNIL; return false;
return tabPtr;
} }
attrPtr.p->data.m_flags = 0; attrPtr.p->data.m_flags = 0;
@ -3045,7 +3073,10 @@ Backup::parseTableDescription(Signal* signal, BackupRecordPtr ptr, Uint32 len)
} }
}//for }//for
if(lcp && disk)
if(lcp)
{
if (disk)
{ {
/** /**
* Remove all disk attributes, but add DISK_REF (8 bytes) * Remove all disk attributes, but add DISK_REF (8 bytes)
@ -3056,15 +3087,44 @@ Backup::parseTableDescription(Signal* signal, BackupRecordPtr ptr, Uint32 len)
ndbrequire(tabPtr.p->attributes.seize(attrPtr)); ndbrequire(tabPtr.p->attributes.seize(attrPtr));
Uint32 sz32 = 2; Uint32 sz32 = 2;
attrPtr.p->data.m_flags = 0;
attrPtr.p->data.attrId = AttributeHeader::DISK_REF; attrPtr.p->data.attrId = AttributeHeader::DISK_REF;
attrPtr.p->data.m_flags = Attribute::COL_FIXED; attrPtr.p->data.m_flags = Attribute::COL_FIXED;
attrPtr.p->data.sz32 = sz32; attrPtr.p->data.sz32 = 2;
attrPtr.p->data.offset = tabPtr.p->sz_FixedAttributes; attrPtr.p->data.offset = tabPtr.p->sz_FixedAttributes;
tabPtr.p->sz_FixedAttributes += sz32; tabPtr.p->sz_FixedAttributes += sz32;
} }
return tabPtr;
{
AttributePtr attrPtr;
ndbrequire(tabPtr.p->attributes.seize(attrPtr));
Uint32 sz32 = 2;
attrPtr.p->data.attrId = AttributeHeader::ROWID;
attrPtr.p->data.m_flags = Attribute::COL_FIXED;
attrPtr.p->data.sz32 = 2;
attrPtr.p->data.offset = tabPtr.p->sz_FixedAttributes;
tabPtr.p->sz_FixedAttributes += sz32;
tabPtr.p->noOfAttributes ++;
}
if (tmpTab.RowGCIFlag)
{
AttributePtr attrPtr;
ndbrequire(tabPtr.p->attributes.seize(attrPtr));
Uint32 sz32 = 2;
attrPtr.p->data.attrId = AttributeHeader::ROW_GCI;
attrPtr.p->data.m_flags = Attribute::COL_FIXED;
attrPtr.p->data.sz32 = 2;
attrPtr.p->data.offset = tabPtr.p->sz_FixedAttributes;
tabPtr.p->sz_FixedAttributes += sz32;
tabPtr.p->noOfAttributes ++;
}
}
return true;
} }
void void

View File

@ -607,7 +607,7 @@ public:
NodeId getMasterNodeId() const { return c_masterNodeId; } NodeId getMasterNodeId() const { return c_masterNodeId; }
bool findTable(const BackupRecordPtr &, TablePtr &, Uint32 tableId) const; bool findTable(const BackupRecordPtr &, TablePtr &, Uint32 tableId) const;
TablePtr parseTableDescription(Signal*, BackupRecordPtr ptr, Uint32 len); bool parseTableDescription(Signal*, BackupRecordPtr ptr, TablePtr, Uint32);
bool insertFileHeader(BackupFormat::FileType, BackupRecord*, BackupFile*); bool insertFileHeader(BackupFormat::FileType, BackupRecord*, BackupFile*);
void sendBackupRef(Signal* signal, BackupRecordPtr ptr, Uint32 errorCode); void sendBackupRef(Signal* signal, BackupRecordPtr ptr, Uint32 errorCode);

View File

@ -115,7 +115,8 @@ struct BackupFormat {
struct TableDescription { struct TableDescription {
Uint32 SectionType; Uint32 SectionType;
Uint32 SectionLength; Uint32 SectionLength;
Uint32 DictTabInfo[1]; // Length = SectionLength - 2 Uint32 TableType;
Uint32 DictTabInfo[1]; // Length = SectionLength - 3
}; };
/** /**

View File

@ -102,12 +102,6 @@ ndbout << "Ptr: " << ptr.p->word32 << " \tIndex: " << tmp_string << " \tValue: "
#define ZDEFAULT_LIST 3 #define ZDEFAULT_LIST 3
#define ZWORDS_IN_PAGE 2048 #define ZWORDS_IN_PAGE 2048
#define ZADDFRAG 0 #define ZADDFRAG 0
#define ZCOPY_NEXT 1
#define ZCOPY_NEXT_COMMIT 2
#define ZCOPY_COMMIT 3
#define ZCOPY_REPEAT 4
#define ZCOPY_ABORT 5
#define ZCOPY_CLOSE 6
#define ZDIRARRAY 68 #define ZDIRARRAY 68
#define ZDIRRANGESIZE 65 #define ZDIRRANGESIZE 65
//#define ZEMPTY_FRAGMENT 0 //#define ZEMPTY_FRAGMENT 0
@ -740,7 +734,7 @@ private:
void releaseRightlist(Signal* signal); void releaseRightlist(Signal* signal);
void checkoverfreelist(Signal* signal); void checkoverfreelist(Signal* signal);
void abortOperation(Signal* signal); void abortOperation(Signal* signal);
void accAbortReqLab(Signal* signal, bool sendConf); void accAbortReqLab(Signal* signal);
void commitOperation(Signal* signal); void commitOperation(Signal* signal);
void copyOpInfo(Signal* signal); void copyOpInfo(Signal* signal);
Uint32 executeNextOperation(Signal* signal); Uint32 executeNextOperation(Signal* signal);

View File

@ -21,6 +21,7 @@
#include <AttributeHeader.hpp> #include <AttributeHeader.hpp>
#include <signaldata/AccFrag.hpp> #include <signaldata/AccFrag.hpp>
#include <signaldata/AccScan.hpp> #include <signaldata/AccScan.hpp>
#include <signaldata/NextScan.hpp>
#include <signaldata/AccLock.hpp> #include <signaldata/AccLock.hpp>
#include <signaldata/EventReport.hpp> #include <signaldata/EventReport.hpp>
#include <signaldata/FsConf.hpp> #include <signaldata/FsConf.hpp>
@ -1072,7 +1073,7 @@ void Dbacc::execACCKEYREQ(Signal* signal)
initOpRec(signal); initOpRec(signal);
// normalize key if any char attr // normalize key if any char attr
if (! operationRecPtr.p->isAccLockReq && fragrecptr.p->hasCharAttr) if (operationRecPtr.p->tupkeylen && fragrecptr.p->hasCharAttr)
xfrmKeyData(signal); xfrmKeyData(signal);
/*---------------------------------------------------------------*/ /*---------------------------------------------------------------*/
@ -1778,12 +1779,13 @@ void Dbacc::execACC_COMMITREQ(Signal* signal)
void Dbacc::execACC_ABORTREQ(Signal* signal) void Dbacc::execACC_ABORTREQ(Signal* signal)
{ {
jamEntry(); jamEntry();
accAbortReqLab(signal, true); accAbortReqLab(signal);
}//Dbacc::execACC_ABORTREQ() }//Dbacc::execACC_ABORTREQ()
void Dbacc::accAbortReqLab(Signal* signal, bool sendConf) void Dbacc::accAbortReqLab(Signal* signal)
{ {
operationRecPtr.i = signal->theData[0]; operationRecPtr.i = signal->theData[0];
bool sendConf = signal->theData[1];
ptrCheckGuard(operationRecPtr, coprecsize, operationrec); ptrCheckGuard(operationRecPtr, coprecsize, operationrec);
tresult = 0; /* ZFALSE */ tresult = 0; /* ZFALSE */
if ((operationRecPtr.p->transactionstate == ACTIVE) || if ((operationRecPtr.p->transactionstate == ACTIVE) ||
@ -1847,6 +1849,7 @@ void Dbacc::execACC_LOCKREQ(Signal* signal)
operationRecPtr.p->userblockref = req->userRef; operationRecPtr.p->userblockref = req->userRef;
operationRecPtr.p->operation = ZUNDEFINED_OP; operationRecPtr.p->operation = ZUNDEFINED_OP;
operationRecPtr.p->transactionstate = IDLE; operationRecPtr.p->transactionstate = IDLE;
operationRecPtr.p->scanRecPtr = RNIL;
// do read with lock via ACCKEYREQ // do read with lock via ACCKEYREQ
Uint32 lockMode = (lockOp == AccLockReq::LockShared) ? 0 : 1; Uint32 lockMode = (lockOp == AccLockReq::LockShared) ? 0 : 1;
Uint32 opCode = ZSCAN_OP; Uint32 opCode = ZSCAN_OP;
@ -1854,7 +1857,7 @@ void Dbacc::execACC_LOCKREQ(Signal* signal)
signal->theData[1] = fragrecptr.i; signal->theData[1] = fragrecptr.i;
signal->theData[2] = opCode | (lockMode << 4) | (1u << 31); signal->theData[2] = opCode | (lockMode << 4) | (1u << 31);
signal->theData[3] = req->hashValue; signal->theData[3] = req->hashValue;
signal->theData[4] = 1; // fake primKeyLen signal->theData[4] = 0; // search local key
signal->theData[5] = req->transId1; signal->theData[5] = req->transId1;
signal->theData[6] = req->transId2; signal->theData[6] = req->transId2;
// enter local key in place of PK // enter local key in place of PK
@ -1896,7 +1899,8 @@ void Dbacc::execACC_LOCKREQ(Signal* signal)
jam(); jam();
// do abort via ACC_ABORTREQ (immediate) // do abort via ACC_ABORTREQ (immediate)
signal->theData[0] = req->accOpPtr; signal->theData[0] = req->accOpPtr;
accAbortReqLab(signal, false); signal->theData[1] = false; // Dont send abort
accAbortReqLab(signal);
releaseOpRec(signal); releaseOpRec(signal);
req->returnCode = AccLockReq::Success; req->returnCode = AccLockReq::Success;
*sig = *req; *sig = *req;
@ -1906,7 +1910,8 @@ void Dbacc::execACC_LOCKREQ(Signal* signal)
jam(); jam();
// do abort via ACC_ABORTREQ (with conf signal) // do abort via ACC_ABORTREQ (with conf signal)
signal->theData[0] = req->accOpPtr; signal->theData[0] = req->accOpPtr;
accAbortReqLab(signal, true); signal->theData[1] = true; // send abort
accAbortReqLab(signal);
releaseOpRec(signal); releaseOpRec(signal);
req->returnCode = AccLockReq::Success; req->returnCode = AccLockReq::Success;
*sig = *req; *sig = *req;
@ -2575,7 +2580,8 @@ Dbacc::readTablePk(Uint32 localkey1)
memset(ckeys, 0x1f, (fragrecptr.p->keyLength * MAX_XFRM_MULTIPLY) << 2); memset(ckeys, 0x1f, (fragrecptr.p->keyLength * MAX_XFRM_MULTIPLY) << 2);
#endif #endif
int ret = c_tup->accReadPk(tableId, fragId, fragPageId, pageIndex, ckeys, true); int ret = c_tup->accReadPk(tableId, fragId, fragPageId, pageIndex, ckeys, true);
ndbrequire(ret > 0); jamEntry();
ndbrequire(ret >= 0);
return ret; return ret;
} }
@ -2632,7 +2638,7 @@ void Dbacc::getElement(Signal* signal)
* - table key for ACCKEYREQ, stored in TUP * - table key for ACCKEYREQ, stored in TUP
* - local key (1 word) for ACC_LOCKREQ and UNDO, stored in ACC * - local key (1 word) for ACC_LOCKREQ and UNDO, stored in ACC
*/ */
const bool searchLocalKey = operationRecPtr.p->isAccLockReq; const bool searchLocalKey = operationRecPtr.p->tupkeylen == 0;
ndbrequire(TelemLen == ZELEM_HEAD_SIZE + fragrecptr.p->localkeylen); ndbrequire(TelemLen == ZELEM_HEAD_SIZE + fragrecptr.p->localkeylen);
tgeNextptrtype = ZLEFT; tgeNextptrtype = ZLEFT;
@ -2775,16 +2781,18 @@ void Dbacc::commitdelete(Signal* signal)
jam(); jam();
Uint32 localKey = operationRecPtr.p->localdata[0]; Uint32 localKey = operationRecPtr.p->localdata[0];
Uint32 userptr= operationRecPtr.p->userptr; Uint32 userptr= operationRecPtr.p->userptr;
Uint32 scanInd = operationRecPtr.p->operation == ZSCAN_OP
|| operationRecPtr.p->isAccLockReq;
signal->theData[0] = fragrecptr.p->myfid; signal->theData[0] = fragrecptr.p->myfid;
signal->theData[1] = fragrecptr.p->myTableId; signal->theData[1] = fragrecptr.p->myTableId;
signal->theData[2] = operationRecPtr.p->localdata[0];
Uint32 pageId = localKey >> MAX_TUPLES_BITS; Uint32 pageId = localKey >> MAX_TUPLES_BITS;
Uint32 pageIndex = localKey & ((1 << MAX_TUPLES_BITS) - 1); Uint32 pageIndex = localKey & ((1 << MAX_TUPLES_BITS) - 1);
signal->theData[2] = pageId; signal->theData[2] = pageId;
signal->theData[3] = pageIndex; signal->theData[3] = pageIndex;
signal->theData[4] = userptr; signal->theData[4] = userptr;
EXECUTE_DIRECT(DBTUP, GSN_TUP_DEALLOCREQ, signal, 5); signal->theData[5] = scanInd;
EXECUTE_DIRECT(DBLQH, GSN_TUP_DEALLOCREQ, signal, 6);
jamEntry(); jamEntry();
getdirindex(signal); getdirindex(signal);
@ -5382,12 +5390,12 @@ void Dbacc::execNEXT_SCANREQ(Signal* signal)
scanPtr.p->scanTimer = scanPtr.p->scanContinuebCounter; scanPtr.p->scanTimer = scanPtr.p->scanContinuebCounter;
switch (tscanNextFlag) { switch (tscanNextFlag) {
case ZCOPY_NEXT: case NextScanReq::ZSCAN_NEXT:
jam(); jam();
/*empty*/; /*empty*/;
break; break;
case ZCOPY_NEXT_COMMIT: case NextScanReq::ZSCAN_NEXT_COMMIT:
case ZCOPY_COMMIT: case NextScanReq::ZSCAN_COMMIT:
jam(); jam();
/* --------------------------------------------------------------------- */ /* --------------------------------------------------------------------- */
/* COMMIT ACTIVE OPERATION. /* COMMIT ACTIVE OPERATION.
@ -5402,7 +5410,7 @@ void Dbacc::execNEXT_SCANREQ(Signal* signal)
takeOutActiveScanOp(signal); takeOutActiveScanOp(signal);
releaseOpRec(signal); releaseOpRec(signal);
scanPtr.p->scanOpsAllocated--; scanPtr.p->scanOpsAllocated--;
if (tscanNextFlag == ZCOPY_COMMIT) { if (tscanNextFlag == NextScanReq::ZSCAN_COMMIT) {
jam(); jam();
signal->theData[0] = scanPtr.p->scanUserptr; signal->theData[0] = scanPtr.p->scanUserptr;
Uint32 blockNo = refToBlock(scanPtr.p->scanUserblockref); Uint32 blockNo = refToBlock(scanPtr.p->scanUserblockref);
@ -5410,7 +5418,7 @@ void Dbacc::execNEXT_SCANREQ(Signal* signal)
return; return;
}//if }//if
break; break;
case ZCOPY_CLOSE: case NextScanReq::ZSCAN_CLOSE:
jam(); jam();
fragrecptr.i = scanPtr.p->activeLocalFrag; fragrecptr.i = scanPtr.p->activeLocalFrag;
ptrCheckGuard(fragrecptr, cfragmentsize, fragmentrec); ptrCheckGuard(fragrecptr, cfragmentsize, fragmentrec);
@ -5995,6 +6003,7 @@ void Dbacc::initScanOpRec(Signal* signal)
scanPtr.p->scanOpsAllocated++; scanPtr.p->scanOpsAllocated++;
operationRecPtr.p->userptr = RNIL;
operationRecPtr.p->scanRecPtr = scanPtr.i; operationRecPtr.p->scanRecPtr = scanPtr.i;
operationRecPtr.p->operation = ZSCAN_OP; operationRecPtr.p->operation = ZSCAN_OP;
operationRecPtr.p->transactionstate = ACTIVE; operationRecPtr.p->transactionstate = ACTIVE;

View File

@ -353,7 +353,9 @@ void Dbdict::packTableIntoPages(Signal* signal)
case DictTabInfo::LogfileGroup:{ case DictTabInfo::LogfileGroup:{
FilegroupPtr fg_ptr; FilegroupPtr fg_ptr;
ndbrequire(c_filegroup_hash.find(fg_ptr, tableId)); ndbrequire(c_filegroup_hash.find(fg_ptr, tableId));
packFilegroupIntoPages(w, fg_ptr); const Uint32 free_hi= signal->theData[4];
const Uint32 free_lo= signal->theData[5];
packFilegroupIntoPages(w, fg_ptr, free_hi, free_lo);
break; break;
} }
case DictTabInfo::Datafile:{ case DictTabInfo::Datafile:{
@ -420,7 +422,13 @@ Dbdict::packTableIntoPages(SimpleProperties::Writer & w,
w.add(DictTabInfo::NoOfVariable, (Uint32)0); w.add(DictTabInfo::NoOfVariable, (Uint32)0);
w.add(DictTabInfo::KeyLength, tablePtr.p->tupKeyLength); w.add(DictTabInfo::KeyLength, tablePtr.p->tupKeyLength);
w.add(DictTabInfo::TableLoggedFlag, tablePtr.p->storedTable); w.add(DictTabInfo::TableLoggedFlag,
!!(tablePtr.p->m_bits & TableRecord::TR_Logged));
w.add(DictTabInfo::RowGCIFlag,
!!(tablePtr.p->m_bits & TableRecord::TR_RowGCI));
w.add(DictTabInfo::RowChecksumFlag,
!!(tablePtr.p->m_bits & TableRecord::TR_RowChecksum));
w.add(DictTabInfo::MinLoadFactor, tablePtr.p->minLoadFactor); w.add(DictTabInfo::MinLoadFactor, tablePtr.p->minLoadFactor);
w.add(DictTabInfo::MaxLoadFactor, tablePtr.p->maxLoadFactor); w.add(DictTabInfo::MaxLoadFactor, tablePtr.p->maxLoadFactor);
w.add(DictTabInfo::TableKValue, tablePtr.p->kValue); w.add(DictTabInfo::TableKValue, tablePtr.p->kValue);
@ -532,7 +540,9 @@ Dbdict::packTableIntoPages(SimpleProperties::Writer & w,
void void
Dbdict::packFilegroupIntoPages(SimpleProperties::Writer & w, Dbdict::packFilegroupIntoPages(SimpleProperties::Writer & w,
FilegroupPtr fg_ptr){ FilegroupPtr fg_ptr,
const Uint32 undo_free_hi,
const Uint32 undo_free_lo){
DictFilegroupInfo::Filegroup fg; fg.init(); DictFilegroupInfo::Filegroup fg; fg.init();
ConstRope r(c_rope_pool, fg_ptr.p->m_name); ConstRope r(c_rope_pool, fg_ptr.p->m_name);
@ -553,6 +563,8 @@ Dbdict::packFilegroupIntoPages(SimpleProperties::Writer & w,
break; break;
case DictTabInfo::LogfileGroup: case DictTabInfo::LogfileGroup:
fg.LF_UndoBufferSize = fg_ptr.p->m_logfilegroup.m_undo_buffer_size; fg.LF_UndoBufferSize = fg_ptr.p->m_logfilegroup.m_undo_buffer_size;
fg.LF_UndoFreeWordsHi= undo_free_hi;
fg.LF_UndoFreeWordsLo= undo_free_lo;
//fg.LF_UndoGrow = ; //fg.LF_UndoGrow = ;
break; break;
default: default:
@ -1794,7 +1806,7 @@ void Dbdict::initialiseTableRecord(TableRecordPtr tablePtr)
tablePtr.p->minLoadFactor = 70; tablePtr.p->minLoadFactor = 70;
tablePtr.p->noOfPrimkey = 1; tablePtr.p->noOfPrimkey = 1;
tablePtr.p->tupKeyLength = 1; tablePtr.p->tupKeyLength = 1;
tablePtr.p->storedTable = true; tablePtr.p->m_bits = 0;
tablePtr.p->tableType = DictTabInfo::UserTable; tablePtr.p->tableType = DictTabInfo::UserTable;
tablePtr.p->primaryTableId = RNIL; tablePtr.p->primaryTableId = RNIL;
// volatile elements // volatile elements
@ -2309,7 +2321,7 @@ Dbdict::rebuildIndexes(Signal* signal, Uint32 i){
req->setParallelism(16); req->setParallelism(16);
// from file index state is not defined currently // from file index state is not defined currently
if (indexPtr.p->storedTable) { if (indexPtr.p->m_bits & TableRecord::TR_Logged) {
// rebuild not needed // rebuild not needed
req->addRequestFlag((Uint32)RequestFlag::RF_NOBUILD); req->addRequestFlag((Uint32)RequestFlag::RF_NOBUILD);
} }
@ -2979,6 +2991,26 @@ Dbdict::execGET_TABINFO_CONF(Signal* signal){
signal->theData[4]= free_extents; signal->theData[4]= free_extents;
sendSignal(reference(), GSN_CONTINUEB, signal, 5, JBB); sendSignal(reference(), GSN_CONTINUEB, signal, 5, JBB);
} }
else if(refToBlock(conf->senderRef) == LGMAN
&& (refToNode(conf->senderRef) == 0
|| refToNode(conf->senderRef) == getOwnNodeId()))
{
jam();
FilegroupPtr fg_ptr;
ndbrequire(c_filegroup_hash.find(fg_ptr, conf->tableId));
const Uint32 free_hi= conf->freeWordsHi;
const Uint32 free_lo= conf->freeWordsLo;
const Uint32 id= conf->tableId;
const Uint32 type= conf->tableType;
const Uint32 data= conf->senderData;
signal->theData[0]= ZPACK_TABLE_INTO_PAGES;
signal->theData[1]= id;
signal->theData[2]= type;
signal->theData[3]= data;
signal->theData[4]= free_hi;
signal->theData[5]= free_lo;
sendSignal(reference(), GSN_CONTINUEB, signal, 6, JBB);
}
else else
{ {
jam(); jam();
@ -5067,7 +5099,7 @@ Dbdict::createTab_dih(Signal* signal,
req->fragType = tabPtr.p->fragmentType; req->fragType = tabPtr.p->fragmentType;
req->kValue = tabPtr.p->kValue; req->kValue = tabPtr.p->kValue;
req->noOfReplicas = 0; req->noOfReplicas = 0;
req->storedTable = tabPtr.p->storedTable; req->storedTable = !!(tabPtr.p->m_bits & TableRecord::TR_Logged);
req->tableType = tabPtr.p->tableType; req->tableType = tabPtr.p->tableType;
req->schemaVersion = tabPtr.p->tableVersion; req->schemaVersion = tabPtr.p->tableVersion;
req->primaryTableId = tabPtr.p->primaryTableId; req->primaryTableId = tabPtr.p->primaryTableId;
@ -5166,6 +5198,7 @@ Dbdict::execADD_FRAGREQ(Signal* signal) {
Uint32 fragCount = req->totalFragments; Uint32 fragCount = req->totalFragments;
Uint32 requestInfo = req->requestInfo; Uint32 requestInfo = req->requestInfo;
Uint32 startGci = req->startGci; Uint32 startGci = req->startGci;
Uint32 logPart = req->logPartId;
ndbrequire(node == getOwnNodeId()); ndbrequire(node == getOwnNodeId());
@ -5215,11 +5248,12 @@ Dbdict::execADD_FRAGREQ(Signal* signal) {
// noOfCharsets passed to TUP in upper half // noOfCharsets passed to TUP in upper half
req->noOfNewAttr |= (tabPtr.p->noOfCharsets << 16); req->noOfNewAttr |= (tabPtr.p->noOfCharsets << 16);
req->checksumIndicator = 1; req->checksumIndicator = 1;
req->GCPIndicator = 0; req->GCPIndicator = 1;
req->startGci = startGci; req->startGci = startGci;
req->tableType = tabPtr.p->tableType; req->tableType = tabPtr.p->tableType;
req->primaryTableId = tabPtr.p->primaryTableId; req->primaryTableId = tabPtr.p->primaryTableId;
req->tablespace_id= tabPtr.p->m_tablespace_id; req->tablespace_id= tabPtr.p->m_tablespace_id;
req->logPartId = logPart;
sendSignal(DBLQH_REF, GSN_LQHFRAGREQ, signal, sendSignal(DBLQH_REF, GSN_LQHFRAGREQ, signal,
LqhFragReq::SignalLength, JBB); LqhFragReq::SignalLength, JBB);
} }
@ -5412,7 +5446,7 @@ Dbdict::execTAB_COMMITCONF(Signal* signal){
signal->theData[0] = tabPtr.i; signal->theData[0] = tabPtr.i;
signal->theData[1] = tabPtr.p->tableVersion; signal->theData[1] = tabPtr.p->tableVersion;
signal->theData[2] = (Uint32)tabPtr.p->storedTable; signal->theData[2] = (Uint32)!!(tabPtr.p->m_bits & TableRecord::TR_Logged);
signal->theData[3] = reference(); signal->theData[3] = reference();
signal->theData[4] = (Uint32)tabPtr.p->tableType; signal->theData[4] = (Uint32)tabPtr.p->tableType;
signal->theData[5] = createTabPtr.p->key; signal->theData[5] = createTabPtr.p->key;
@ -5816,7 +5850,12 @@ void Dbdict::handleTabInfoInit(SimpleProperties::Reader & it,
} }
tablePtr.p->noOfAttributes = tableDesc.NoOfAttributes; tablePtr.p->noOfAttributes = tableDesc.NoOfAttributes;
tablePtr.p->storedTable = tableDesc.TableLoggedFlag; tablePtr.p->m_bits |=
(tableDesc.TableLoggedFlag ? TableRecord::TR_Logged : 0);
tablePtr.p->m_bits |=
(tableDesc.RowChecksumFlag ? TableRecord::TR_RowChecksum : 0);
tablePtr.p->m_bits |=
(tableDesc.RowGCIFlag ? TableRecord::TR_RowGCI : 0);
tablePtr.p->minLoadFactor = tableDesc.MinLoadFactor; tablePtr.p->minLoadFactor = tableDesc.MinLoadFactor;
tablePtr.p->maxLoadFactor = tableDesc.MaxLoadFactor; tablePtr.p->maxLoadFactor = tableDesc.MaxLoadFactor;
tablePtr.p->fragmentType = (DictTabInfo::FragmentType)tableDesc.FragmentType; tablePtr.p->fragmentType = (DictTabInfo::FragmentType)tableDesc.FragmentType;
@ -5853,7 +5892,7 @@ void Dbdict::handleTabInfoInit(SimpleProperties::Reader & it,
tablePtr.p->buildTriggerId = RNIL; tablePtr.p->buildTriggerId = RNIL;
tablePtr.p->indexLocal = 0; tablePtr.p->indexLocal = 0;
handleTabInfo(it, parseP, tableDesc.TablespaceVersion); handleTabInfo(it, parseP, tableDesc);
if(parseP->errorCode != 0) if(parseP->errorCode != 0)
{ {
@ -5866,7 +5905,7 @@ void Dbdict::handleTabInfoInit(SimpleProperties::Reader & it,
void Dbdict::handleTabInfo(SimpleProperties::Reader & it, void Dbdict::handleTabInfo(SimpleProperties::Reader & it,
ParseDictTabInfoRecord * parseP, ParseDictTabInfoRecord * parseP,
Uint32 tablespaceVersion) DictTabInfo::Table &tableDesc)
{ {
TableRecordPtr tablePtr = parseP->tablePtr; TableRecordPtr tablePtr = parseP->tablePtr;
@ -6105,7 +6144,7 @@ void Dbdict::handleTabInfo(SimpleProperties::Reader & it,
tabRequire(false, CreateTableRef::NotATablespace); tabRequire(false, CreateTableRef::NotATablespace);
} }
if(tablespacePtr.p->m_version != tablespaceVersion) if(tablespacePtr.p->m_version != tableDesc.TablespaceVersion)
{ {
tabRequire(false, CreateTableRef::InvalidTablespaceVersion); tabRequire(false, CreateTableRef::InvalidTablespaceVersion);
} }
@ -7061,6 +7100,18 @@ void Dbdict::execGET_TABINFOREQ(Signal* signal)
sendSignal(TSMAN_REF, GSN_GET_TABINFOREQ, signal, sendSignal(TSMAN_REF, GSN_GET_TABINFOREQ, signal,
GetTabInfoReq::SignalLength, JBB); GetTabInfoReq::SignalLength, JBB);
} }
else if(objEntry->m_tableType==DictTabInfo::LogfileGroup)
{
jam();
GetTabInfoReq *req= (GetTabInfoReq*)signal->theData;
req->senderData= c_retrieveRecord.retrievePage;
req->senderRef= reference();
req->requestType= GetTabInfoReq::RequestById;
req->tableId= obj_id;
sendSignal(LGMAN_REF, GSN_GET_TABINFOREQ, signal,
GetTabInfoReq::SignalLength, JBB);
}
else else
{ {
jam(); jam();
@ -7209,7 +7260,7 @@ Dbdict::execLIST_TABLES_REQ(Signal* signal)
} }
} }
// store // store
if (! tablePtr.p->storedTable) { if (! (tablePtr.p->m_bits & TableRecord::TR_Logged)) {
conf->setTableStore(pos, DictTabInfo::StoreTemporary); conf->setTableStore(pos, DictTabInfo::StoreTemporary);
} else { } else {
conf->setTableStore(pos, DictTabInfo::StorePermanent); conf->setTableStore(pos, DictTabInfo::StorePermanent);
@ -7242,6 +7293,7 @@ Dbdict::execLIST_TABLES_REQ(Signal* signal)
conf->tableData[pos] = 0; conf->tableData[pos] = 0;
conf->setTableId(pos, iter.curr.p->m_id); conf->setTableId(pos, iter.curr.p->m_id);
conf->setTableType(pos, type); // type conf->setTableType(pos, type); // type
conf->setTableState(pos, DictTabInfo::StateOnline); // XXX todo
pos++; pos++;
} }
if (DictTabInfo::isFile(type)){ if (DictTabInfo::isFile(type)){
@ -7249,6 +7301,7 @@ Dbdict::execLIST_TABLES_REQ(Signal* signal)
conf->tableData[pos] = 0; conf->tableData[pos] = 0;
conf->setTableId(pos, iter.curr.p->m_id); conf->setTableId(pos, iter.curr.p->m_id);
conf->setTableType(pos, type); // type conf->setTableType(pos, type); // type
conf->setTableState(pos, DictTabInfo::StateOnline); // XXX todo
pos++; pos++;
} }
@ -7570,8 +7623,9 @@ Dbdict::createIndex_toCreateTable(Signal* signal, OpCreateIndexPtr opPtr)
indexPtr.i = RNIL; // invalid indexPtr.i = RNIL; // invalid
indexPtr.p = &indexRec; indexPtr.p = &indexRec;
initialiseTableRecord(indexPtr); initialiseTableRecord(indexPtr);
indexPtr.p->m_bits = TableRecord::TR_RowChecksum;
if (req->getIndexType() == DictTabInfo::UniqueHashIndex) { if (req->getIndexType() == DictTabInfo::UniqueHashIndex) {
indexPtr.p->storedTable = opPtr.p->m_storedIndex; indexPtr.p->m_bits |= (opPtr.p->m_storedIndex ? TableRecord::TR_Logged:0);
indexPtr.p->fragmentType = DictTabInfo::DistrKeyUniqueHashIndex; indexPtr.p->fragmentType = DictTabInfo::DistrKeyUniqueHashIndex;
} else if (req->getIndexType() == DictTabInfo::OrderedIndex) { } else if (req->getIndexType() == DictTabInfo::OrderedIndex) {
// first version will not supported logging // first version will not supported logging
@ -7581,7 +7635,6 @@ Dbdict::createIndex_toCreateTable(Signal* signal, OpCreateIndexPtr opPtr)
opPtr.p->m_errorLine = __LINE__; opPtr.p->m_errorLine = __LINE__;
return; return;
} }
indexPtr.p->storedTable = false;
indexPtr.p->fragmentType = DictTabInfo::DistrKeyOrderedIndex; indexPtr.p->fragmentType = DictTabInfo::DistrKeyOrderedIndex;
} else { } else {
jam(); jam();
@ -7665,7 +7718,7 @@ Dbdict::createIndex_toCreateTable(Signal* signal, OpCreateIndexPtr opPtr)
indexPtr.p->noOfNullAttr = 0; indexPtr.p->noOfNullAttr = 0;
// write index table // write index table
w.add(DictTabInfo::TableName, opPtr.p->m_indexName); w.add(DictTabInfo::TableName, opPtr.p->m_indexName);
w.add(DictTabInfo::TableLoggedFlag, indexPtr.p->storedTable); w.add(DictTabInfo::TableLoggedFlag, !!(indexPtr.p->m_bits & TableRecord::TR_Logged));
w.add(DictTabInfo::FragmentTypeVal, indexPtr.p->fragmentType); w.add(DictTabInfo::FragmentTypeVal, indexPtr.p->fragmentType);
w.add(DictTabInfo::TableTypeVal, indexPtr.p->tableType); w.add(DictTabInfo::TableTypeVal, indexPtr.p->tableType);
Rope name(c_rope_pool, tablePtr.p->tableName); Rope name(c_rope_pool, tablePtr.p->tableName);
@ -13817,6 +13870,7 @@ Dbdict::execCREATE_OBJ_REQ(Signal* signal){
createObjPtr.p->m_obj_type = objType; createObjPtr.p->m_obj_type = objType;
createObjPtr.p->m_obj_version = objVersion; createObjPtr.p->m_obj_version = objVersion;
createObjPtr.p->m_obj_info_ptr_i = objInfoPtr.i; createObjPtr.p->m_obj_info_ptr_i = objInfoPtr.i;
createObjPtr.p->m_obj_ptr_i = RNIL;
createObjPtr.p->m_callback.m_callbackData = key; createObjPtr.p->m_callback.m_callbackData = key;
createObjPtr.p->m_callback.m_callbackFunction= createObjPtr.p->m_callback.m_callbackFunction=
@ -14514,6 +14568,9 @@ Dbdict::create_fg_prepare_start(Signal* signal, SchemaOp* op){
getSection(objInfoPtr, ((OpCreateObj*)op)->m_obj_info_ptr_i); getSection(objInfoPtr, ((OpCreateObj*)op)->m_obj_info_ptr_i);
SimplePropertiesSectionReader it(objInfoPtr, getSectionSegmentPool()); SimplePropertiesSectionReader it(objInfoPtr, getSectionSegmentPool());
Ptr<DictObject> obj_ptr; obj_ptr.setNull();
FilegroupPtr fg_ptr; fg_ptr.setNull();
SimpleProperties::UnpackStatus status; SimpleProperties::UnpackStatus status;
DictFilegroupInfo::Filegroup fg; fg.init(); DictFilegroupInfo::Filegroup fg; fg.init();
do { do {
@ -14552,15 +14609,12 @@ Dbdict::create_fg_prepare_start(Signal* signal, SchemaOp* op){
break; break;
} }
Ptr<DictObject> obj_ptr;
if(!c_obj_pool.seize(obj_ptr)){ if(!c_obj_pool.seize(obj_ptr)){
op->m_errorCode = CreateTableRef::NoMoreTableRecords; op->m_errorCode = CreateTableRef::NoMoreTableRecords;
break; break;
} }
FilegroupPtr fg_ptr;
if(!c_filegroup_pool.seize(fg_ptr)){ if(!c_filegroup_pool.seize(fg_ptr)){
c_obj_pool.release(obj_ptr);
op->m_errorCode = CreateTableRef::NoMoreTableRecords; op->m_errorCode = CreateTableRef::NoMoreTableRecords;
break; break;
} }
@ -14569,8 +14623,6 @@ Dbdict::create_fg_prepare_start(Signal* signal, SchemaOp* op){
Rope name(c_rope_pool, obj_ptr.p->m_name); Rope name(c_rope_pool, obj_ptr.p->m_name);
if(!name.assign(fg.FilegroupName, len, hash)){ if(!name.assign(fg.FilegroupName, len, hash)){
op->m_errorCode = CreateTableRef::TableNameTooLong; op->m_errorCode = CreateTableRef::TableNameTooLong;
c_obj_pool.release(obj_ptr);
c_filegroup_pool.release(fg_ptr);
break; break;
} }
} }
@ -14620,6 +14672,22 @@ Dbdict::create_fg_prepare_start(Signal* signal, SchemaOp* op){
} while(0); } while(0);
error: error:
if (op->m_errorCode)
{
jam();
if (!fg_ptr.isNull())
{
jam();
c_filegroup_pool.release(fg_ptr);
}
if (!obj_ptr.isNull())
{
jam();
c_obj_pool.release(obj_ptr);
}
}
execute(signal, op->m_callback, 0); execute(signal, op->m_callback, 0);
} }
@ -14690,14 +14758,33 @@ Dbdict::execCREATE_FILEGROUP_CONF(Signal* signal){
void void
Dbdict::create_fg_abort_start(Signal* signal, SchemaOp* op){ Dbdict::create_fg_abort_start(Signal* signal, SchemaOp* op){
CreateFilegroupImplReq* req =
(CreateFilegroupImplReq*)signal->getDataPtrSend();
if (op->m_obj_ptr_i != RNIL)
{
jam();
send_drop_fg(signal, op, DropFilegroupImplReq::Commit);
return;
}
execute(signal, op->m_callback, 0); execute(signal, op->m_callback, 0);
abort();
} }
void void
Dbdict::create_fg_abort_complete(Signal* signal, SchemaOp* op){ Dbdict::create_fg_abort_complete(Signal* signal, SchemaOp* op){
if (op->m_obj_ptr_i != RNIL)
{
jam();
FilegroupPtr fg_ptr;
c_filegroup_pool.getPtr(fg_ptr, op->m_obj_ptr_i);
release_object(fg_ptr.p->m_obj_ptr_i);
c_filegroup_hash.release(fg_ptr);
}
execute(signal, op->m_callback, 0); execute(signal, op->m_callback, 0);
abort();
} }
void void
@ -14709,6 +14796,9 @@ Dbdict::create_file_prepare_start(Signal* signal, SchemaOp* op){
getSection(objInfoPtr, ((OpCreateObj*)op)->m_obj_info_ptr_i); getSection(objInfoPtr, ((OpCreateObj*)op)->m_obj_info_ptr_i);
SimplePropertiesSectionReader it(objInfoPtr, getSectionSegmentPool()); SimplePropertiesSectionReader it(objInfoPtr, getSectionSegmentPool());
Ptr<DictObject> obj_ptr; obj_ptr.setNull();
FilePtr filePtr; filePtr.setNull();
DictFilegroupInfo::File f; f.init(); DictFilegroupInfo::File f; f.init();
SimpleProperties::UnpackStatus status; SimpleProperties::UnpackStatus status;
status = SimpleProperties::unpack(it, &f, status = SimpleProperties::unpack(it, &f,
@ -14758,16 +14848,13 @@ Dbdict::create_file_prepare_start(Signal* signal, SchemaOp* op){
} }
// Loop through all filenames... // Loop through all filenames...
Ptr<DictObject> obj_ptr;
if(!c_obj_pool.seize(obj_ptr)){ if(!c_obj_pool.seize(obj_ptr)){
op->m_errorCode = CreateTableRef::NoMoreTableRecords; op->m_errorCode = CreateTableRef::NoMoreTableRecords;
break; break;
} }
FilePtr filePtr;
if (! c_file_pool.seize(filePtr)){ if (! c_file_pool.seize(filePtr)){
op->m_errorCode = CreateFileRef::OutOfFileRecords; op->m_errorCode = CreateFileRef::OutOfFileRecords;
c_obj_pool.release(obj_ptr);
break; break;
} }
@ -14775,8 +14862,6 @@ Dbdict::create_file_prepare_start(Signal* signal, SchemaOp* op){
Rope name(c_rope_pool, obj_ptr.p->m_name); Rope name(c_rope_pool, obj_ptr.p->m_name);
if(!name.assign(f.FileName, len, hash)){ if(!name.assign(f.FileName, len, hash)){
op->m_errorCode = CreateTableRef::TableNameTooLong; op->m_errorCode = CreateTableRef::TableNameTooLong;
c_obj_pool.release(obj_ptr);
c_file_pool.release(filePtr);
break; break;
} }
} }
@ -14814,6 +14899,22 @@ Dbdict::create_file_prepare_start(Signal* signal, SchemaOp* op){
op->m_obj_ptr_i = filePtr.i; op->m_obj_ptr_i = filePtr.i;
} while(0); } while(0);
if (op->m_errorCode)
{
jam();
if (!filePtr.isNull())
{
jam();
c_file_pool.release(filePtr);
}
if (!obj_ptr.isNull())
{
jam();
c_obj_pool.release(obj_ptr);
}
}
execute(signal, op->m_callback, 0); execute(signal, op->m_callback, 0);
} }
@ -14839,8 +14940,6 @@ Dbdict::create_file_prepare_complete(Signal* signal, SchemaOp* op){
break; break;
case 1: case 1:
req->requestInfo = CreateFileImplReq::Open; req->requestInfo = CreateFileImplReq::Open;
if(getNodeState().getNodeRestartInProgress())
req->requestInfo = CreateFileImplReq::CreateForce;
break; break;
case 2: case 2:
req->requestInfo = CreateFileImplReq::CreateForce; req->requestInfo = CreateFileImplReq::CreateForce;
@ -14946,6 +15045,8 @@ Dbdict::create_file_abort_start(Signal* signal, SchemaOp* op)
{ {
CreateFileImplReq* req = (CreateFileImplReq*)signal->getDataPtrSend(); CreateFileImplReq* req = (CreateFileImplReq*)signal->getDataPtrSend();
if (op->m_obj_ptr_i != RNIL)
{
FilePtr f_ptr; FilePtr f_ptr;
c_file_pool.getPtr(f_ptr, op->m_obj_ptr_i); c_file_pool.getPtr(f_ptr, op->m_obj_ptr_i);
@ -14974,11 +15075,17 @@ Dbdict::create_file_abort_start(Signal* signal, SchemaOp* op)
sendSignal(ref, GSN_CREATE_FILE_REQ, signal, sendSignal(ref, GSN_CREATE_FILE_REQ, signal,
CreateFileImplReq::AbortLength, JBB); CreateFileImplReq::AbortLength, JBB);
return;
}
execute(signal, op->m_callback, 0);
} }
void void
Dbdict::create_file_abort_complete(Signal* signal, SchemaOp* op) Dbdict::create_file_abort_complete(Signal* signal, SchemaOp* op)
{ {
if (op->m_obj_ptr_i != RNIL)
{
FilePtr f_ptr; FilePtr f_ptr;
c_file_pool.getPtr(f_ptr, op->m_obj_ptr_i); c_file_pool.getPtr(f_ptr, op->m_obj_ptr_i);
@ -15000,6 +15107,8 @@ Dbdict::create_file_abort_complete(Signal* signal, SchemaOp* op)
} }
release_object(f_ptr.p->m_obj_ptr_i); release_object(f_ptr.p->m_obj_ptr_i);
c_file_pool.release(f_ptr);
}
execute(signal, op->m_callback, 0); execute(signal, op->m_callback, 0);
} }
@ -15036,6 +15145,7 @@ Dbdict::drop_file_commit_complete(Signal* signal, SchemaOp* op)
decrease_ref_count(fg_ptr.p->m_obj_ptr_i); decrease_ref_count(fg_ptr.p->m_obj_ptr_i);
release_object(f_ptr.p->m_obj_ptr_i); release_object(f_ptr.p->m_obj_ptr_i);
c_file_pool.release(f_ptr);
execute(signal, op->m_callback, 0); execute(signal, op->m_callback, 0);
} }
@ -15223,6 +15333,7 @@ Dbdict::drop_fg_commit_complete(Signal* signal, SchemaOp* op)
c_filegroup_pool.getPtr(fg_ptr, op->m_obj_ptr_i); c_filegroup_pool.getPtr(fg_ptr, op->m_obj_ptr_i);
release_object(fg_ptr.p->m_obj_ptr_i); release_object(fg_ptr.p->m_obj_ptr_i);
c_filegroup_hash.release(fg_ptr);
execute(signal, op->m_callback, 0); execute(signal, op->m_callback, 0);
} }

View File

@ -228,6 +228,15 @@ public:
/* Global checkpoint identity when table created */ /* Global checkpoint identity when table created */
Uint32 gciTableCreated; Uint32 gciTableCreated;
/* Is the table logged (i.e. data survives system restart) */
enum Bits
{
TR_Logged = 0x1,
TR_RowGCI = 0x2,
TR_RowChecksum = 0x4
};
Uint16 m_bits;
/* Number of attibutes in table */ /* Number of attibutes in table */
Uint16 noOfAttributes; Uint16 noOfAttributes;
@ -266,9 +275,6 @@ public:
*/ */
Uint8 minLoadFactor; Uint8 minLoadFactor;
/* Is the table logged (i.e. data survives system restart) */
bool storedTable;
/* Convenience routines */ /* Convenience routines */
bool isTable() const; bool isTable() const;
bool isIndex() const; bool isIndex() const;
@ -508,6 +514,7 @@ public:
Uint32 m_filegroup_id; Uint32 m_filegroup_id;
Uint32 m_type; Uint32 m_type;
Uint64 m_file_size; Uint64 m_file_size;
Uint64 m_file_free;
RopeHandle m_path; RopeHandle m_path;
Uint32 nextList; Uint32 nextList;
@ -2001,7 +2008,10 @@ private:
AttributeRecordPtr & attrPtr); AttributeRecordPtr & attrPtr);
void packTableIntoPages(Signal* signal); void packTableIntoPages(Signal* signal);
void packTableIntoPages(SimpleProperties::Writer &, TableRecordPtr, Signal* =0); void packTableIntoPages(SimpleProperties::Writer &, TableRecordPtr, Signal* =0);
void packFilegroupIntoPages(SimpleProperties::Writer &, FilegroupPtr); void packFilegroupIntoPages(SimpleProperties::Writer &,
FilegroupPtr,
const Uint32 undo_free_hi,
const Uint32 undo_free_lo);
void packFileIntoPages(SimpleProperties::Writer &, FilePtr, const Uint32); void packFileIntoPages(SimpleProperties::Writer &, FilePtr, const Uint32);
void sendGET_TABINFOREQ(Signal* signal, void sendGET_TABINFOREQ(Signal* signal,
@ -2026,7 +2036,7 @@ private:
ParseDictTabInfoRecord *, ParseDictTabInfoRecord *,
bool checkExist = true); bool checkExist = true);
void handleTabInfo(SimpleProperties::Reader & it, ParseDictTabInfoRecord *, void handleTabInfo(SimpleProperties::Reader & it, ParseDictTabInfoRecord *,
Uint32 tablespaceVersion); DictTabInfo::Table & tableDesc);
void handleAddTableFailure(Signal* signal, void handleAddTableFailure(Signal* signal,
Uint32 failureLine, Uint32 failureLine,

View File

@ -238,6 +238,8 @@ public:
Uint32 storedReplicas; /* "ALIVE" STORED REPLICAS */ Uint32 storedReplicas; /* "ALIVE" STORED REPLICAS */
Uint32 nextFragmentChunk; Uint32 nextFragmentChunk;
Uint32 m_log_part_id;
Uint8 distributionKey; Uint8 distributionKey;
Uint8 fragReplicas; Uint8 fragReplicas;
Uint8 noOldStoredReplicas; /* NUMBER OF "DEAD" STORED REPLICAS */ Uint8 noOldStoredReplicas; /* NUMBER OF "DEAD" STORED REPLICAS */
@ -545,7 +547,9 @@ public:
TO_END_COPY = 19, TO_END_COPY = 19,
TO_END_COPY_ONGOING = 20, TO_END_COPY_ONGOING = 20,
TO_WAIT_ENDING = 21, TO_WAIT_ENDING = 21,
ENDING = 22 ENDING = 22,
STARTING_LOCAL_FRAGMENTS = 24
}; };
enum ToSlaveStatus { enum ToSlaveStatus {
TO_SLAVE_IDLE = 0, TO_SLAVE_IDLE = 0,
@ -974,7 +978,9 @@ private:
void initialiseRecordsLab(Signal *, Uint32 stepNo, Uint32, Uint32); void initialiseRecordsLab(Signal *, Uint32 stepNo, Uint32, Uint32);
void findReplica(ReplicaRecordPtr& regReplicaPtr, void findReplica(ReplicaRecordPtr& regReplicaPtr,
Fragmentstore* fragPtrP, Uint32 nodeId); Fragmentstore* fragPtrP,
Uint32 nodeId,
bool oldStoredReplicas = false);
//------------------------------------ //------------------------------------
// Node failure handling methods // Node failure handling methods
//------------------------------------ //------------------------------------
@ -1132,6 +1138,10 @@ private:
void setNodeCopyCompleted(Uint32 nodeId, bool newState); void setNodeCopyCompleted(Uint32 nodeId, bool newState);
bool checkNodeAlive(Uint32 nodeId); bool checkNodeAlive(Uint32 nodeId);
void nr_start_fragments(Signal*, TakeOverRecordPtr);
void nr_start_fragment(Signal*, TakeOverRecordPtr, ReplicaRecordPtr);
void nr_run_redo(Signal*, TakeOverRecordPtr);
// Initialisation // Initialisation
void initData(); void initData();
void initRecords(); void initRecords();
@ -1158,6 +1168,7 @@ private:
Uint32 c_nextNodeGroup; Uint32 c_nextNodeGroup;
NodeGroupRecord *nodeGroupRecord; NodeGroupRecord *nodeGroupRecord;
Uint32 c_nextLogPart;
NodeRecord *nodeRecord; NodeRecord *nodeRecord;

View File

@ -609,6 +609,14 @@ void Dbdih::execCONTINUEB(Signal* signal)
checkWaitDropTabFailedLqh(signal, nodeId, tableId); checkWaitDropTabFailedLqh(signal, nodeId, tableId);
return; return;
} }
case DihContinueB::ZTO_START_FRAGMENTS:
{
TakeOverRecordPtr takeOverPtr;
takeOverPtr.i = signal->theData[1];
ptrCheckGuard(takeOverPtr, MAX_NDB_NODES, takeOverRecord);
nr_start_fragments(signal, takeOverPtr);
return;
}
}//switch }//switch
ndbrequire(false); ndbrequire(false);
@ -1771,11 +1779,6 @@ void Dbdih::execSTART_MEREQ(Signal* signal)
ndbrequire(c_nodeStartMaster.startNode == Tnodeid); ndbrequire(c_nodeStartMaster.startNode == Tnodeid);
ndbrequire(getNodeStatus(Tnodeid) == NodeRecord::STARTING); ndbrequire(getNodeStatus(Tnodeid) == NodeRecord::STARTING);
sendSTART_RECREQ(signal, Tnodeid);
}//Dbdih::execSTART_MEREQ()
void Dbdih::nodeRestartStartRecConfLab(Signal* signal)
{
c_nodeStartMaster.blockLcp = true; c_nodeStartMaster.blockLcp = true;
if ((c_lcpState.lcpStatus != LCP_STATUS_IDLE) && if ((c_lcpState.lcpStatus != LCP_STATUS_IDLE) &&
(c_lcpState.lcpStatus != LCP_TCGET)) { (c_lcpState.lcpStatus != LCP_TCGET)) {
@ -2586,13 +2589,14 @@ void Dbdih::sendStartTo(Signal* signal, Uint32 takeOverPtrI)
return; return;
}//if }//if
c_startToLock = takeOverPtrI; c_startToLock = takeOverPtrI;
takeOverPtr.p->toMasterStatus = TakeOverRecord::STARTING;
StartToReq * const req = (StartToReq *)&signal->theData[0]; StartToReq * const req = (StartToReq *)&signal->theData[0];
req->userPtr = takeOverPtr.i; req->userPtr = takeOverPtr.i;
req->userRef = reference(); req->userRef = reference();
req->startingNodeId = takeOverPtr.p->toStartingNode; req->startingNodeId = takeOverPtr.p->toStartingNode;
req->nodeTakenOver = takeOverPtr.p->toFailedNode; req->nodeTakenOver = takeOverPtr.p->toFailedNode;
req->nodeRestart = takeOverPtr.p->toNodeRestart; req->nodeRestart = takeOverPtr.p->toNodeRestart;
takeOverPtr.p->toMasterStatus = TakeOverRecord::STARTING;
sendLoopMacro(START_TOREQ, sendSTART_TOREQ); sendLoopMacro(START_TOREQ, sendSTART_TOREQ);
}//Dbdih::sendStartTo() }//Dbdih::sendStartTo()
@ -2636,9 +2640,153 @@ void Dbdih::execSTART_TOCONF(Signal* signal)
CRASH_INSERTION(7134); CRASH_INSERTION(7134);
c_startToLock = RNIL; c_startToLock = RNIL;
if (takeOverPtr.p->toNodeRestart)
{
jam();
takeOverPtr.p->toMasterStatus = TakeOverRecord::STARTING_LOCAL_FRAGMENTS;
nr_start_fragments(signal, takeOverPtr);
return;
}
startNextCopyFragment(signal, takeOverPtr.i); startNextCopyFragment(signal, takeOverPtr.i);
}//Dbdih::execSTART_TOCONF() }//Dbdih::execSTART_TOCONF()
void
Dbdih::nr_start_fragments(Signal* signal,
TakeOverRecordPtr takeOverPtr)
{
Uint32 loopCount = 0 ;
TabRecordPtr tabPtr;
while (loopCount++ < 100) {
tabPtr.i = takeOverPtr.p->toCurrentTabref;
if (tabPtr.i >= ctabFileSize) {
jam();
nr_run_redo(signal, takeOverPtr);
return;
}//if
ptrAss(tabPtr, tabRecord);
if (tabPtr.p->tabStatus != TabRecord::TS_ACTIVE){
jam();
takeOverPtr.p->toCurrentFragid = 0;
takeOverPtr.p->toCurrentTabref++;
continue;
}//if
Uint32 fragId = takeOverPtr.p->toCurrentFragid;
if (fragId >= tabPtr.p->totalfragments) {
jam();
takeOverPtr.p->toCurrentFragid = 0;
takeOverPtr.p->toCurrentTabref++;
continue;
}//if
FragmentstorePtr fragPtr;
getFragstore(tabPtr.p, fragId, fragPtr);
ReplicaRecordPtr loopReplicaPtr;
loopReplicaPtr.i = fragPtr.p->oldStoredReplicas;
while (loopReplicaPtr.i != RNIL) {
ptrCheckGuard(loopReplicaPtr, creplicaFileSize, replicaRecord);
if (loopReplicaPtr.p->procNode == takeOverPtr.p->toStartingNode) {
jam();
nr_start_fragment(signal, takeOverPtr, loopReplicaPtr);
break;
} else {
jam();
loopReplicaPtr.i = loopReplicaPtr.p->nextReplica;
}//if
}//while
takeOverPtr.p->toCurrentFragid++;
}//while
signal->theData[0] = DihContinueB::ZTO_START_FRAGMENTS;
signal->theData[1] = takeOverPtr.i;
sendSignal(reference(), GSN_CONTINUEB, signal, 2, JBB);
}
void
Dbdih::nr_start_fragment(Signal* signal,
TakeOverRecordPtr takeOverPtr,
ReplicaRecordPtr replicaPtr)
{
Uint32 i, j = 0;
Uint32 maxLcpId = 0;
Uint32 maxLcpIndex = ~0;
Uint32 restorableGCI = 0;
ndbout_c("tab: %d frag: %d replicaP->nextLcp: %d",
takeOverPtr.p->toCurrentTabref,
takeOverPtr.p->toCurrentFragid,
replicaPtr.p->nextLcp);
Uint32 idx = replicaPtr.p->nextLcp;
for(i = 0; i<MAX_LCP_STORED; i++, idx = nextLcpNo(idx))
{
ndbout_c("scanning idx: %d lcpId: %d", idx, replicaPtr.p->lcpId[idx]);
if (replicaPtr.p->lcpStatus[idx] == ZVALID)
{
ndbrequire(replicaPtr.p->lcpId[idx] > maxLcpId);
Uint32 startGci = replicaPtr.p->maxGciCompleted[idx];
Uint32 stopGci = replicaPtr.p->maxGciStarted[idx];
for (;j < replicaPtr.p->noCrashedReplicas; j++)
{
ndbout_c("crashed replica: %d(%d) replicaLastGci: %d",
j,
replicaPtr.p->noCrashedReplicas,
replicaPtr.p->replicaLastGci[j]);
if (replicaPtr.p->replicaLastGci[j] > stopGci)
{
maxLcpId = replicaPtr.p->lcpId[idx];
maxLcpIndex = idx;
restorableGCI = replicaPtr.p->replicaLastGci[j];
break;
}
}
}
}
if (maxLcpIndex == ~0)
{
ndbout_c("Didnt find any LCP for node: %d tab: %d frag: %d",
takeOverPtr.p->toStartingNode,
takeOverPtr.p->toCurrentTabref,
takeOverPtr.p->toCurrentFragid);
replicaPtr.p->lcpIdStarted = 0;
}
else
{
ndbout_c("Found LCP: %d(%d) maxGciStarted: %d maxGciCompleted: %d restorable: %d(%d) newestRestorableGCI: %d",
maxLcpId,
maxLcpIndex,
replicaPtr.p->maxGciStarted[maxLcpIndex],
replicaPtr.p->maxGciCompleted[maxLcpIndex],
restorableGCI,
SYSFILE->lastCompletedGCI[takeOverPtr.p->toStartingNode],
SYSFILE->newestRestorableGCI);
replicaPtr.p->lcpIdStarted = restorableGCI;
BlockReference ref = calcLqhBlockRef(takeOverPtr.p->toStartingNode);
StartFragReq *req = (StartFragReq *)signal->getDataPtrSend();
req->userPtr = 0;
req->userRef = reference();
req->lcpNo = maxLcpIndex;
req->lcpId = maxLcpId;
req->tableId = takeOverPtr.p->toCurrentTabref;
req->fragId = takeOverPtr.p->toCurrentFragid;
req->noOfLogNodes = 1;
req->lqhLogNode[0] = takeOverPtr.p->toStartingNode;
req->startGci[0] = replicaPtr.p->maxGciCompleted[maxLcpIndex];
req->lastGci[0] = restorableGCI;
sendSignal(ref, GSN_START_FRAGREQ, signal,
StartFragReq::SignalLength, JBB);
}
}
void
Dbdih::nr_run_redo(Signal* signal, TakeOverRecordPtr takeOverPtr)
{
takeOverPtr.p->toCurrentTabref = 0;
takeOverPtr.p->toCurrentFragid = 0;
sendSTART_RECREQ(signal, takeOverPtr.p->toStartingNode);
}
void Dbdih::initStartTakeOver(const StartToReq * req, void Dbdih::initStartTakeOver(const StartToReq * req,
TakeOverRecordPtr takeOverPtr) TakeOverRecordPtr takeOverPtr)
{ {
@ -2971,6 +3119,14 @@ void Dbdih::execCREATE_FRAGCONF(Signal* signal)
/*---------------------------------------------------------------------- */ /*---------------------------------------------------------------------- */
FragmentstorePtr fragPtr; FragmentstorePtr fragPtr;
getFragstore(tabPtr.p, fragId, fragPtr); getFragstore(tabPtr.p, fragId, fragPtr);
Uint32 gci = 0;
if (takeOverPtr.p->toNodeRestart)
{
ReplicaRecordPtr replicaPtr;
findReplica(replicaPtr, fragPtr.p, takeOverPtr.p->toStartingNode, true);
gci = replicaPtr.p->lcpIdStarted;
replicaPtr.p->lcpIdStarted = 0;
}
takeOverPtr.p->toMasterStatus = TakeOverRecord::COPY_FRAG; takeOverPtr.p->toMasterStatus = TakeOverRecord::COPY_FRAG;
BlockReference ref = calcLqhBlockRef(takeOverPtr.p->toCopyNode); BlockReference ref = calcLqhBlockRef(takeOverPtr.p->toCopyNode);
CopyFragReq * const copyFragReq = (CopyFragReq *)&signal->theData[0]; CopyFragReq * const copyFragReq = (CopyFragReq *)&signal->theData[0];
@ -2981,6 +3137,7 @@ void Dbdih::execCREATE_FRAGCONF(Signal* signal)
copyFragReq->nodeId = takeOverPtr.p->toStartingNode; copyFragReq->nodeId = takeOverPtr.p->toStartingNode;
copyFragReq->schemaVersion = tabPtr.p->schemaVersion; copyFragReq->schemaVersion = tabPtr.p->schemaVersion;
copyFragReq->distributionKey = fragPtr.p->distributionKey; copyFragReq->distributionKey = fragPtr.p->distributionKey;
copyFragReq->gci = gci;
sendSignal(ref, GSN_COPY_FRAGREQ, signal, CopyFragReq::SignalLength, JBB); sendSignal(ref, GSN_COPY_FRAGREQ, signal, CopyFragReq::SignalLength, JBB);
} else { } else {
ndbrequire(takeOverPtr.p->toMasterStatus == TakeOverRecord::COMMIT_CREATE); ndbrequire(takeOverPtr.p->toMasterStatus == TakeOverRecord::COMMIT_CREATE);
@ -4033,6 +4190,8 @@ void Dbdih::checkTakeOverInMasterStartNodeFailure(Signal* signal,
Uint32 takeOverPtrI) Uint32 takeOverPtrI)
{ {
jam(); jam();
ndbout_c("checkTakeOverInMasterStartNodeFailure %x",
takeOverPtrI);
if (takeOverPtrI == RNIL) { if (takeOverPtrI == RNIL) {
jam(); jam();
return; return;
@ -4046,6 +4205,9 @@ void Dbdih::checkTakeOverInMasterStartNodeFailure(Signal* signal,
takeOverPtr.i = takeOverPtrI; takeOverPtr.i = takeOverPtrI;
ptrCheckGuard(takeOverPtr, MAX_NDB_NODES, takeOverRecord); ptrCheckGuard(takeOverPtr, MAX_NDB_NODES, takeOverRecord);
ndbout_c("takeOverPtr.p->toMasterStatus: %x",
takeOverPtr.p->toMasterStatus);
bool ok = false; bool ok = false;
switch (takeOverPtr.p->toMasterStatus) { switch (takeOverPtr.p->toMasterStatus) {
case TakeOverRecord::IDLE: case TakeOverRecord::IDLE:
@ -4154,6 +4316,13 @@ void Dbdih::checkTakeOverInMasterStartNodeFailure(Signal* signal,
//----------------------------------------------------------------------- //-----------------------------------------------------------------------
endTakeOver(takeOverPtr.i); endTakeOver(takeOverPtr.i);
break; break;
case TakeOverRecord::STARTING_LOCAL_FRAGMENTS:
ok = true;
jam();
endTakeOver(takeOverPtr.i);
break;
/** /**
* The following are states that it should not be possible to "be" in * The following are states that it should not be possible to "be" in
*/ */
@ -6585,6 +6754,8 @@ void Dbdih::execDIADDTABREQ(Signal* signal)
Uint32 activeIndex = 0; Uint32 activeIndex = 0;
getFragstore(tabPtr.p, fragId, fragPtr); getFragstore(tabPtr.p, fragId, fragPtr);
fragPtr.p->preferredPrimary = fragments[index]; fragPtr.p->preferredPrimary = fragments[index];
fragPtr.p->m_log_part_id = c_nextLogPart++;
for (Uint32 i = 0; i<noReplicas; i++) { for (Uint32 i = 0; i<noReplicas; i++) {
const Uint32 nodeId = fragments[index++]; const Uint32 nodeId = fragments[index++];
ReplicaRecordPtr replicaPtr; ReplicaRecordPtr replicaPtr;
@ -6629,9 +6800,9 @@ Dbdih::sendAddFragreq(Signal* signal, ConnectRecordPtr connectPtr,
jam(); jam();
const Uint32 fragCount = tabPtr.p->totalfragments; const Uint32 fragCount = tabPtr.p->totalfragments;
ReplicaRecordPtr replicaPtr; replicaPtr.i = RNIL; ReplicaRecordPtr replicaPtr; replicaPtr.i = RNIL;
FragmentstorePtr fragPtr;
for(; fragId<fragCount; fragId++){ for(; fragId<fragCount; fragId++){
jam(); jam();
FragmentstorePtr fragPtr;
getFragstore(tabPtr.p, fragId, fragPtr); getFragstore(tabPtr.p, fragId, fragPtr);
replicaPtr.i = fragPtr.p->storedReplicas; replicaPtr.i = fragPtr.p->storedReplicas;
@ -6689,6 +6860,7 @@ Dbdih::sendAddFragreq(Signal* signal, ConnectRecordPtr connectPtr,
req->nodeId = getOwnNodeId(); req->nodeId = getOwnNodeId();
req->totalFragments = fragCount; req->totalFragments = fragCount;
req->startGci = SYSFILE->newestRestorableGCI; req->startGci = SYSFILE->newestRestorableGCI;
req->logPartId = fragPtr.p->m_log_part_id;
sendSignal(DBDICT_REF, GSN_ADD_FRAGREQ, signal, sendSignal(DBDICT_REF, GSN_ADD_FRAGREQ, signal,
AddFragReq::SignalLength, JBB); AddFragReq::SignalLength, JBB);
return; return;
@ -8875,8 +9047,8 @@ void Dbdih::execSTART_RECCONF(Signal* signal)
// otherwise we have a problem. // otherwise we have a problem.
/* --------------------------------------------------------------------- */ /* --------------------------------------------------------------------- */
jam(); jam();
ndbrequire(senderNodeId == c_nodeStartMaster.startNode); ndbout_c("startNextCopyFragment");
nodeRestartStartRecConfLab(signal); startNextCopyFragment(signal, findTakeOver(senderNodeId));
return; return;
} else { } else {
/* --------------------------------------------------------------------- */ /* --------------------------------------------------------------------- */
@ -9895,9 +10067,11 @@ Dbdih::checkLcpAllTablesDoneInLqh(){
} }
void Dbdih::findReplica(ReplicaRecordPtr& replicaPtr, void Dbdih::findReplica(ReplicaRecordPtr& replicaPtr,
Fragmentstore* fragPtrP, Uint32 nodeId) Fragmentstore* fragPtrP,
Uint32 nodeId,
bool old)
{ {
replicaPtr.i = fragPtrP->storedReplicas; replicaPtr.i = old ? fragPtrP->oldStoredReplicas : fragPtrP->storedReplicas;
while(replicaPtr.i != RNIL){ while(replicaPtr.i != RNIL){
ptrCheckGuard(replicaPtr, creplicaFileSize, replicaRecord); ptrCheckGuard(replicaPtr, creplicaFileSize, replicaRecord);
if (replicaPtr.p->procNode == nodeId) { if (replicaPtr.p->procNode == nodeId) {
@ -11168,6 +11342,7 @@ void Dbdih::initCommonData()
currentgcp = 0; currentgcp = 0;
cverifyQueueCounter = 0; cverifyQueueCounter = 0;
cwaitLcpSr = false; cwaitLcpSr = false;
c_nextLogPart = 0;
nodeResetStart(); nodeResetStart();
c_nodeStartMaster.wait = ZFALSE; c_nodeStartMaster.wait = ZFALSE;
@ -11972,6 +12147,8 @@ void Dbdih::readFragment(RWFragment* rf, FragmentstorePtr fragPtr)
jam(); jam();
fragPtr.p->distributionKey = TdistKey; fragPtr.p->distributionKey = TdistKey;
}//if }//if
fragPtr.p->m_log_part_id = readPageWord(rf);
}//Dbdih::readFragment() }//Dbdih::readFragment()
Uint32 Dbdih::readPageWord(RWFragment* rf) Uint32 Dbdih::readPageWord(RWFragment* rf)
@ -13062,6 +13239,7 @@ void Dbdih::writeFragment(RWFragment* wf, FragmentstorePtr fragPtr)
writePageWord(wf, fragPtr.p->noStoredReplicas); writePageWord(wf, fragPtr.p->noStoredReplicas);
writePageWord(wf, fragPtr.p->noOldStoredReplicas); writePageWord(wf, fragPtr.p->noOldStoredReplicas);
writePageWord(wf, fragPtr.p->distributionKey); writePageWord(wf, fragPtr.p->distributionKey);
writePageWord(wf, fragPtr.p->m_log_part_id);
}//Dbdih::writeFragment() }//Dbdih::writeFragment()
void Dbdih::writePageWord(RWFragment* wf, Uint32 dataWord) void Dbdih::writePageWord(RWFragment* wf, Uint32 dataWord)

View File

@ -142,7 +142,7 @@
/* ------------------------------------------------------------------------- */ /* ------------------------------------------------------------------------- */
#define ZFD_HEADER_SIZE 3 #define ZFD_HEADER_SIZE 3
#define ZFD_PART_SIZE 48 #define ZFD_PART_SIZE 48
#define ZLOG_HEAD_SIZE 6 #define ZLOG_HEAD_SIZE 8
#define ZNEXT_LOG_SIZE 2 #define ZNEXT_LOG_SIZE 2
#define ZABORT_LOG_SIZE 3 #define ZABORT_LOG_SIZE 3
#define ZCOMMIT_LOG_SIZE 9 #define ZCOMMIT_LOG_SIZE 9
@ -264,15 +264,6 @@
#define ZSTORED_PROC_SCAN 0 #define ZSTORED_PROC_SCAN 0
#define ZSTORED_PROC_COPY 2 #define ZSTORED_PROC_COPY 2
#define ZDELETE_STORED_PROC_ID 3 #define ZDELETE_STORED_PROC_ID 3
//#define ZSCAN_NEXT 1
//#define ZSCAN_NEXT_COMMIT 2
//#define ZSCAN_NEXT_ABORT 12
#define ZCOPY_COMMIT 3
#define ZCOPY_REPEAT 4
#define ZCOPY_ABORT 5
#define ZCOPY_CLOSE 6
//#define ZSCAN_CLOSE 6
//#define ZEMPTY_FRAGMENT 0
#define ZWRITE_LOCK 1 #define ZWRITE_LOCK 1
#define ZSCAN_FRAG_CLOSED 2 #define ZSCAN_FRAG_CLOSED 2
/* ------------------------------------------------------------------------- */ /* ------------------------------------------------------------------------- */
@ -525,7 +516,7 @@ public:
Uint32 scan_acc_index; Uint32 scan_acc_index;
Uint32 scan_acc_attr_recs; Uint32 scan_acc_attr_recs;
UintR scanApiOpPtr; UintR scanApiOpPtr;
UintR scanLocalref[2]; Local_key m_row_id;
Uint32 m_max_batch_size_rows; Uint32 m_max_batch_size_rows;
Uint32 m_max_batch_size_bytes; Uint32 m_max_batch_size_bytes;
@ -553,7 +544,6 @@ public:
UintR scanAccPtr; UintR scanAccPtr;
UintR scanAiLength; UintR scanAiLength;
UintR scanErrorCounter; UintR scanErrorCounter;
UintR scanLocalFragid;
UintR scanSchemaVersion; UintR scanSchemaVersion;
/** /**
@ -747,10 +737,16 @@ public:
FragStatus fragStatus; FragStatus fragStatus;
/** /**
* Indicates a local checkpoint is active and thus can generate * 0 = undefined i.e fragStatus != ACTIVE_CREATION
* UNDO log records. * 1 = yes
* 2 = no
*/ */
UintR fragActiveStatus; enum ActiveCreat {
AC_NORMAL = 0, // fragStatus != ACTIVE_CREATION
AC_IGNORED = 1, // Operation that got ignored during NR
AC_NR_COPY = 2 // Operation that got performed during NR
};
Uint8 m_copy_started_state;
/** /**
* This flag indicates whether logging is currently activated at * This flag indicates whether logging is currently activated at
@ -889,6 +885,11 @@ public:
* fragment in primary table. * fragment in primary table.
*/ */
UintR tableFragptr; UintR tableFragptr;
/**
* Log part
*/
Uint32 m_log_part_ptr_i;
}; };
typedef Ptr<Fragrecord> FragrecordPtr; typedef Ptr<Fragrecord> FragrecordPtr;
@ -2030,7 +2031,16 @@ public:
Uint8 seqNoReplica; Uint8 seqNoReplica;
Uint8 tcNodeFailrec; Uint8 tcNodeFailrec;
Uint8 m_disk_table; Uint8 m_disk_table;
Uint32 m_local_key; Uint8 m_use_rowid;
Uint8 m_dealloc;
Uint32 m_log_part_ptr_i;
Local_key m_row_id;
struct {
Uint32 m_cnt;
Uint32 m_page_id[2];
Local_key m_disk_ref[2];
} m_nr_delete;
}; /* p2c: size = 280 bytes */ }; /* p2c: size = 280 bytes */
typedef Ptr<TcConnectionrec> TcConnectionrecPtr; typedef Ptr<TcConnectionrec> TcConnectionrecPtr;
@ -2095,10 +2105,6 @@ private:
void execBUILDINDXCONF(Signal*signal); void execBUILDINDXCONF(Signal*signal);
void execDUMP_STATE_ORD(Signal* signal); void execDUMP_STATE_ORD(Signal* signal);
void execACC_COM_BLOCK(Signal* signal);
void execACC_COM_UNBLOCK(Signal* signal);
void execTUP_COM_BLOCK(Signal* signal);
void execTUP_COM_UNBLOCK(Signal* signal);
void execACC_ABORTCONF(Signal* signal); void execACC_ABORTCONF(Signal* signal);
void execNODE_FAILREP(Signal* signal); void execNODE_FAILREP(Signal* signal);
void execCHECK_LCP_STOP(Signal* signal); void execCHECK_LCP_STOP(Signal* signal);
@ -2181,6 +2187,7 @@ private:
void execDROP_TAB_REQ(Signal* signal); void execDROP_TAB_REQ(Signal* signal);
void execLQH_ALLOCREQ(Signal* signal); void execLQH_ALLOCREQ(Signal* signal);
void execTUP_DEALLOCREQ(Signal* signal);
void execLQH_WRITELOG_REQ(Signal* signal); void execLQH_WRITELOG_REQ(Signal* signal);
void execTUXFRAGCONF(Signal* signal); void execTUXFRAGCONF(Signal* signal);
@ -2234,7 +2241,7 @@ private:
Uint32 sendKeyinfo20(Signal* signal, ScanRecord *, TcConnectionrec *); Uint32 sendKeyinfo20(Signal* signal, ScanRecord *, TcConnectionrec *);
void sendScanFragConf(Signal* signal, Uint32 scanCompleted); void sendScanFragConf(Signal* signal, Uint32 scanCompleted);
void initCopyrec(Signal* signal); void initCopyrec(Signal* signal);
void initCopyTc(Signal* signal); void initCopyTc(Signal* signal, Operation_t);
void sendCopyActiveConf(Signal* signal,Uint32 tableId); void sendCopyActiveConf(Signal* signal,Uint32 tableId);
void checkLcpCompleted(Signal* signal); void checkLcpCompleted(Signal* signal);
void checkLcpHoldop(Signal* signal); void checkLcpHoldop(Signal* signal);
@ -2277,7 +2284,7 @@ private:
void checkReadExecSr(Signal* signal); void checkReadExecSr(Signal* signal);
void checkScanTcCompleted(Signal* signal); void checkScanTcCompleted(Signal* signal);
void checkSrCompleted(Signal* signal); void checkSrCompleted(Signal* signal);
void closeFile(Signal* signal, LogFileRecordPtr logFilePtr); void closeFile(Signal* signal, LogFileRecordPtr logFilePtr, Uint32 place);
void completedLogPage(Signal* signal, Uint32 clpType, Uint32 place); void completedLogPage(Signal* signal, Uint32 clpType, Uint32 place);
void deleteFragrec(Uint32 fragId); void deleteFragrec(Uint32 fragId);
void deleteTransidHash(Signal* signal); void deleteTransidHash(Signal* signal);
@ -2562,6 +2569,22 @@ private:
void acckeyconf_tupkeyreq(Signal*, TcConnectionrec*, Fragrecord*, Uint32, Uint32); void acckeyconf_tupkeyreq(Signal*, TcConnectionrec*, Fragrecord*, Uint32, Uint32);
void acckeyconf_load_diskpage(Signal*,TcConnectionrecPtr,Fragrecord*,Uint32); void acckeyconf_load_diskpage(Signal*,TcConnectionrecPtr,Fragrecord*,Uint32);
void handle_nr_copy(Signal*, Ptr<TcConnectionrec>);
void exec_acckeyreq(Signal*, Ptr<TcConnectionrec>);
int compare_key(const TcConnectionrec*, const Uint32 * ptr, Uint32 len);
void nr_copy_delete_row(Signal*, Ptr<TcConnectionrec>, Local_key*, Uint32);
public:
struct Nr_op_info
{
Uint32 m_ptr_i;
Uint32 m_tup_frag_ptr_i;
Uint32 m_gci;
Uint32 m_page_id;
Local_key m_disk_ref;
};
void get_nr_op_info(Nr_op_info*, Uint32 page_id = RNIL);
void nr_delete_complete(Signal*, Nr_op_info*);
public: public:
void acckeyconf_load_diskpage_callback(Signal*, Uint32, Uint32); void acckeyconf_load_diskpage_callback(Signal*, Uint32, Uint32);
@ -2823,11 +2846,6 @@ private:
UintR cLqhTimeOutCount; UintR cLqhTimeOutCount;
UintR cLqhTimeOutCheckCount; UintR cLqhTimeOutCheckCount;
UintR cnoOfLogPages; UintR cnoOfLogPages;
bool caccCommitBlocked;
bool ctupCommitBlocked;
bool cCommitBlocked;
UintR cCounterAccCommitBlocked;
UintR cCounterTupCommitBlocked;
/* ------------------------------------------------------------------------- */ /* ------------------------------------------------------------------------- */
/*THIS VARIABLE CONTAINS MY OWN PROCESSOR ID. */ /*THIS VARIABLE CONTAINS MY OWN PROCESSOR ID. */
/* ------------------------------------------------------------------------- */ /* ------------------------------------------------------------------------- */
@ -2847,17 +2865,12 @@ private:
Uint16 cpackedList[MAX_NDB_NODES]; Uint16 cpackedList[MAX_NDB_NODES];
UintR cnodeData[MAX_NDB_NODES]; UintR cnodeData[MAX_NDB_NODES];
UintR cnodeStatus[MAX_NDB_NODES]; UintR cnodeStatus[MAX_NDB_NODES];
/* ------------------------------------------------------------------------- */
/*THIS VARIABLE INDICATES WHETHER A CERTAIN NODE HAS SENT ALL FRAGMENTS THAT */
/*NEED TO HAVE THE LOG EXECUTED. */
/* ------------------------------------------------------------------------- */
Uint8 cnodeSrState[MAX_NDB_NODES];
/* ------------------------------------------------------------------------- */
/*THIS VARIABLE INDICATES WHETHER A CERTAIN NODE HAVE EXECUTED THE LOG */
/* ------------------------------------------------------------------------- */
Uint8 cnodeExecSrState[MAX_NDB_NODES];
UintR cnoOfNodes; UintR cnoOfNodes;
NdbNodeBitmask m_sr_nodes;
NdbNodeBitmask m_sr_exec_sr_req;
NdbNodeBitmask m_sr_exec_sr_conf;
/* ------------------------------------------------------------------------- */ /* ------------------------------------------------------------------------- */
/* THIS VARIABLE CONTAINS THE DIRECTORY OF A HASH TABLE OF ALL ACTIVE */ /* THIS VARIABLE CONTAINS THE DIRECTORY OF A HASH TABLE OF ALL ACTIVE */
/* OPERATION IN THE BLOCK. IT IS USED TO BE ABLE TO QUICKLY ABORT AN */ /* OPERATION IN THE BLOCK. IT IS USED TO BE ABLE TO QUICKLY ABORT AN */
@ -2985,6 +2998,10 @@ Dblqh::accminupdate(Signal* signal, Uint32 opId, const Local_key* key)
signal->theData[0] = regTcPtr.p->accConnectrec; signal->theData[0] = regTcPtr.p->accConnectrec;
signal->theData[1] = key->m_page_no << MAX_TUPLES_BITS | key->m_page_idx; signal->theData[1] = key->m_page_no << MAX_TUPLES_BITS | key->m_page_idx;
c_acc->execACCMINUPDATE(signal); c_acc->execACCMINUPDATE(signal);
if (ERROR_INSERTED(5712))
ndbout << " LK: " << *key;
regTcPtr.p->m_row_id = *key;
} }

View File

@ -221,10 +221,6 @@ Dblqh::Dblqh(const class Configuration & conf):
addRecSignal(GSN_DROP_TRIG_REF, &Dblqh::execDROP_TRIG_REF); addRecSignal(GSN_DROP_TRIG_REF, &Dblqh::execDROP_TRIG_REF);
addRecSignal(GSN_DUMP_STATE_ORD, &Dblqh::execDUMP_STATE_ORD); addRecSignal(GSN_DUMP_STATE_ORD, &Dblqh::execDUMP_STATE_ORD);
addRecSignal(GSN_ACC_COM_BLOCK, &Dblqh::execACC_COM_BLOCK);
addRecSignal(GSN_ACC_COM_UNBLOCK, &Dblqh::execACC_COM_UNBLOCK);
addRecSignal(GSN_TUP_COM_BLOCK, &Dblqh::execTUP_COM_BLOCK);
addRecSignal(GSN_TUP_COM_UNBLOCK, &Dblqh::execTUP_COM_UNBLOCK);
addRecSignal(GSN_NODE_FAILREP, &Dblqh::execNODE_FAILREP); addRecSignal(GSN_NODE_FAILREP, &Dblqh::execNODE_FAILREP);
addRecSignal(GSN_CHECK_LCP_STOP, &Dblqh::execCHECK_LCP_STOP); addRecSignal(GSN_CHECK_LCP_STOP, &Dblqh::execCHECK_LCP_STOP);
addRecSignal(GSN_SEND_PACKED, &Dblqh::execSEND_PACKED); addRecSignal(GSN_SEND_PACKED, &Dblqh::execSEND_PACKED);
@ -301,6 +297,7 @@ Dblqh::Dblqh(const class Configuration & conf):
addRecSignal(GSN_LQH_ALLOCREQ, &Dblqh::execLQH_ALLOCREQ); addRecSignal(GSN_LQH_ALLOCREQ, &Dblqh::execLQH_ALLOCREQ);
addRecSignal(GSN_LQH_WRITELOG_REQ, &Dblqh::execLQH_WRITELOG_REQ); addRecSignal(GSN_LQH_WRITELOG_REQ, &Dblqh::execLQH_WRITELOG_REQ);
addRecSignal(GSN_TUP_DEALLOCREQ, &Dblqh::execTUP_DEALLOCREQ);
// TUX // TUX
addRecSignal(GSN_TUXFRAGCONF, &Dblqh::execTUXFRAGCONF); addRecSignal(GSN_TUXFRAGCONF, &Dblqh::execTUXFRAGCONF);

File diff suppressed because it is too large Load Diff

View File

@ -128,7 +128,7 @@ bool PrepareOperationRecord::check() {
if (m_operationType == 3 && m_attributeLength != 0) if (m_operationType == 3 && m_attributeLength != 0)
return false; return false;
if (m_logRecordSize != (m_attributeLength + m_keyLength + 6)) if (m_logRecordSize != (m_attributeLength + m_keyLength + 8))
return false; return false;
return true; return true;
@ -165,6 +165,8 @@ NdbOut& operator<<(NdbOut& no, const PrepareOperationRecord& por) {
default: default:
printOut("operationType:", por.m_operationType); printOut("operationType:", por.m_operationType);
} }
printOut("page_no: ", por.m_page_no);
printOut("page_idx: ", por.m_page_idx);
printOut("attributeLength:", por.m_attributeLength); printOut("attributeLength:", por.m_attributeLength);
printOut("keyLength:", por.m_keyLength); printOut("keyLength:", por.m_keyLength);

View File

@ -92,6 +92,8 @@ protected:
Uint32 m_operationType; // 0 READ, 1 UPDATE, 2 INSERT, 3 DELETE Uint32 m_operationType; // 0 READ, 1 UPDATE, 2 INSERT, 3 DELETE
Uint32 m_attributeLength; Uint32 m_attributeLength;
Uint32 m_keyLength; Uint32 m_keyLength;
Uint32 m_page_no;
Uint32 m_page_idx;
Uint32 *m_keyInfo; // In this order Uint32 *m_keyInfo; // In this order
Uint32 *m_attrInfo;// In this order Uint32 *m_attrInfo;// In this order
}; };

View File

@ -892,11 +892,7 @@ public:
*/ */
Uint8 opExec; Uint8 opExec;
/** Uint8 unused;
* LOCK TYPE OF OPERATION IF READ OPERATION
* 0 = READ LOCK, 1 = WRITE LOCK
*/
Uint8 opLock;
/** /**
* IS THE OPERATION A SIMPLE TRANSACTION * IS THE OPERATION A SIMPLE TRANSACTION

View File

@ -2807,17 +2807,9 @@ void Dbtc::execTCKEYREQ(Signal* signal)
regCachePtr->attrinfo15[2] = Tdata4; regCachePtr->attrinfo15[2] = Tdata4;
regCachePtr->attrinfo15[3] = Tdata5; regCachePtr->attrinfo15[3] = Tdata5;
if (TOperationType == ZREAD) { if (TOperationType == ZREAD || TOperationType == ZREAD_EX) {
Uint32 TreadCount = c_counters.creadCount; Uint32 TreadCount = c_counters.creadCount;
jam(); jam();
regCachePtr->opLock = 0;
c_counters.creadCount = TreadCount + 1;
} else if(TOperationType == ZREAD_EX){
Uint32 TreadCount = c_counters.creadCount;
jam();
TOperationType = ZREAD;
regTcPtr->operation = ZREAD;
regCachePtr->opLock = ZUPDATE;
c_counters.creadCount = TreadCount + 1; c_counters.creadCount = TreadCount + 1;
} else { } else {
if(regApiPtr->commitAckMarker == RNIL){ if(regApiPtr->commitAckMarker == RNIL){
@ -2851,24 +2843,10 @@ void Dbtc::execTCKEYREQ(Signal* signal)
c_counters.cwriteCount = TwriteCount + 1; c_counters.cwriteCount = TwriteCount + 1;
switch (TOperationType) { switch (TOperationType) {
case ZUPDATE: case ZUPDATE:
jam();
if (TattrLen == 0) {
//TCKEY_abort(signal, 5);
//return;
}//if
/*---------------------------------------------------------------------*/
// The missing break is intentional since we also want to set the opLock
// variable also for updates
/*---------------------------------------------------------------------*/
case ZINSERT: case ZINSERT:
case ZDELETE: case ZDELETE:
jam();
regCachePtr->opLock = TOperationType;
break;
case ZWRITE: case ZWRITE:
jam(); jam();
// A write operation is originally an insert operation.
regCachePtr->opLock = ZINSERT;
break; break;
default: default:
TCKEY_abort(signal, 9); TCKEY_abort(signal, 9);
@ -3039,7 +3017,7 @@ void Dbtc::tckeyreq050Lab(Signal* signal)
tnoOfStandby = (tnodeinfo >> 8) & 3; tnoOfStandby = (tnodeinfo >> 8) & 3;
regCachePtr->fragmentDistributionKey = (tnodeinfo >> 16) & 255; regCachePtr->fragmentDistributionKey = (tnodeinfo >> 16) & 255;
if (Toperation == ZREAD) { if (Toperation == ZREAD || Toperation == ZREAD_EX) {
if (Tdirty == 1) { if (Tdirty == 1) {
jam(); jam();
/*-------------------------------------------------------------*/ /*-------------------------------------------------------------*/
@ -3168,6 +3146,7 @@ void Dbtc::sendlqhkeyreq(Signal* signal,
TcConnectRecord * const regTcPtr = tcConnectptr.p; TcConnectRecord * const regTcPtr = tcConnectptr.p;
ApiConnectRecord * const regApiPtr = apiConnectptr.p; ApiConnectRecord * const regApiPtr = apiConnectptr.p;
CacheRecord * const regCachePtr = cachePtr.p; CacheRecord * const regCachePtr = cachePtr.p;
Uint32 version = getNodeInfo(refToNode(TBRef)).m_version;
#ifdef ERROR_INSERT #ifdef ERROR_INSERT
if (ERROR_INSERTED(8002)) { if (ERROR_INSERTED(8002)) {
systemErrorLab(signal, __LINE__); systemErrorLab(signal, __LINE__);
@ -3207,7 +3186,12 @@ void Dbtc::sendlqhkeyreq(Signal* signal,
Tdata10 = 0; Tdata10 = 0;
LqhKeyReq::setKeyLen(Tdata10, regCachePtr->keylen); LqhKeyReq::setKeyLen(Tdata10, regCachePtr->keylen);
LqhKeyReq::setLastReplicaNo(Tdata10, regTcPtr->lastReplicaNo); LqhKeyReq::setLastReplicaNo(Tdata10, regTcPtr->lastReplicaNo);
LqhKeyReq::setLockType(Tdata10, regCachePtr->opLock); if (unlikely(version < NDBD_ROWID_VERSION))
{
Uint32 op = regTcPtr->operation;
Uint32 lock = op == ZREAD_EX ? ZUPDATE : op == ZWRITE ? ZINSERT : op;
LqhKeyReq::setLockType(Tdata10, lock);
}
/* ---------------------------------------------------------------------- */ /* ---------------------------------------------------------------------- */
// Indicate Application Reference is present in bit 15 // Indicate Application Reference is present in bit 15
/* ---------------------------------------------------------------------- */ /* ---------------------------------------------------------------------- */

View File

@ -177,7 +177,7 @@ inline const Uint32* ALIGN_WORD(const void* ptr)
#define ZINSERT_ERROR 630 #define ZINSERT_ERROR 630
#define ZINVALID_CHAR_FORMAT 744 #define ZINVALID_CHAR_FORMAT 744
#define ZROWID_ALLOCATED 899
/* SOME WORD POSITIONS OF FIELDS IN SOME HEADERS */ /* SOME WORD POSITIONS OF FIELDS IN SOME HEADERS */
@ -235,8 +235,9 @@ inline const Uint32* ALIGN_WORD(const void* ptr)
#define ZREL_FRAG 7 #define ZREL_FRAG 7
#define ZREPORT_MEMORY_USAGE 8 #define ZREPORT_MEMORY_USAGE 8
#define ZBUILD_INDEX 9 #define ZBUILD_INDEX 9
#define ZFREE_EXTENT 10 #define ZTUP_SCAN 10
#define ZUNMAP_PAGES 11 #define ZFREE_EXTENT 11
#define ZUNMAP_PAGES 12
#define ZSCAN_PROCEDURE 0 #define ZSCAN_PROCEDURE 0
#define ZCOPY_PROCEDURE 2 #define ZCOPY_PROCEDURE 2
@ -336,40 +337,106 @@ struct Fragoperrec {
}; };
typedef Ptr<Fragoperrec> FragoperrecPtr; typedef Ptr<Fragoperrec> FragoperrecPtr;
// Position for use by scan
struct PagePos { typedef Tup_page Page;
typedef Ptr<Page> PagePtr;
// Scan position
struct ScanPos {
enum Get {
Get_undef = 0,
Get_next_page,
Get_page,
Get_next_page_mm,
Get_page_mm,
Get_next_page_dd,
Get_page_dd,
Get_next_tuple,
Get_tuple,
Get_next_tuple_fs,
Get_tuple_fs
};
Get m_get; // entry point in scanNext
Local_key m_key; // scan position pointer MM or DD
Page* m_page; // scanned MM or DD (cache) page
Local_key m_key_mm; // MM local key returned
Uint32 m_realpid_mm; // MM real page id
Uint32 m_extent_info_ptr_i; Uint32 m_extent_info_ptr_i;
Local_key m_key;
bool m_match;
}; };
// Tup scan op (compare Dbtux::ScanOp) // Scan Lock
struct ScanLock {
Uint32 m_accLockOp;
union {
Uint32 nextPool;
Uint32 nextList;
};
Uint32 prevList;
};
typedef Ptr<ScanLock> ScanLockPtr;
ArrayPool<ScanLock> c_scanLockPool;
// Tup scan, similar to Tux scan. Later some of this could
// be moved to common superclass.
struct ScanOp { struct ScanOp {
ScanOp() {} ScanOp() :
enum { // state m_state(Undef),
m_bits(0),
m_userPtr(RNIL),
m_userRef(RNIL),
m_tableId(RNIL),
m_fragId(~(Uint32)0),
m_fragPtrI(RNIL),
m_transId1(0),
m_transId2(0),
m_savePointId(0),
m_accLockOp(RNIL)
{}
enum State {
Undef = 0, Undef = 0,
First = 1, // before first entry First = 1, // before first entry
Locked = 4, // at current entry (no lock needed) Current = 2, // at current before locking
Blocked = 3, // at current waiting for ACC lock
Locked = 4, // at current and locked or no lock needed
Next = 5, // looking for next extry Next = 5, // looking for next extry
Last = 6, // after last entry Last = 6, // after last entry
Aborting = 7, // lock wait at scan close
Invalid = 9 // cannot return REF to LQH currently Invalid = 9 // cannot return REF to LQH currently
}; };
Uint16 m_state; Uint16 m_state;
STATIC_CONST( SCAN_DD = 0x1 ); enum Bits {
STATIC_CONST( SCAN_VS = 0x2 ); SCAN_DD = 0x01, // scan disk pages
STATIC_CONST( SCAN_LCP = 0x4 ); SCAN_VS = 0x02, // page format is var size
STATIC_CONST( SCAN_DD_VS = 0x8 ); SCAN_LCP = 0x04, // LCP mem page scan
SCAN_LOCK_SH = 0x10, // lock mode shared
SCAN_LOCK_EX = 0x20, // lock mode exclusive
SCAN_LOCK_WAIT = 0x40, // lock wait
// any lock mode
SCAN_LOCK = SCAN_LOCK_SH | SCAN_LOCK_EX,
SCAN_NR = 0x80 // Node recovery scan
};
Uint16 m_bits; Uint16 m_bits;
Uint32 m_userPtr; // scanptr.i in LQH Uint32 m_userPtr; // scanptr.i in LQH
Uint32 m_userRef; Uint32 m_userRef;
Uint32 m_tableId; Uint32 m_tableId;
Uint32 m_fragId; // "base" fragment id Uint32 m_fragId;
Uint32 m_fragPtrI; Uint32 m_fragPtrI;
Uint32 m_transId1; Uint32 m_transId1;
Uint32 m_transId2; Uint32 m_transId2;
PagePos m_scanPos; union {
Uint32 m_savePointId;
Uint32 m_scanGCI;
};
// lock waited for or obtained and not yet passed to LQH
Uint32 m_accLockOp;
ScanPos m_scanPos;
DLFifoList<ScanLock>::Head m_accLockOps;
union { union {
Uint32 nextPool; Uint32 nextPool;
Uint32 nextList; Uint32 nextList;
@ -379,8 +446,18 @@ typedef Ptr<Fragoperrec> FragoperrecPtr;
typedef Ptr<ScanOp> ScanOpPtr; typedef Ptr<ScanOp> ScanOpPtr;
ArrayPool<ScanOp> c_scanOpPool; ArrayPool<ScanOp> c_scanOpPool;
typedef Tup_page Page; void scanReply(Signal*, ScanOpPtr scanPtr);
typedef Ptr<Page> PagePtr; void scanFirst(Signal*, ScanOpPtr scanPtr);
bool scanNext(Signal*, ScanOpPtr scanPtr);
void scanCont(Signal*, ScanOpPtr scanPtr);
void disk_page_tup_scan_callback(Signal*, Uint32 scanPtrI, Uint32 page_i);
void scanClose(Signal*, ScanOpPtr scanPtr);
void addAccLockOp(ScanOp& scan, Uint32 accLockOp);
void removeAccLockOp(ScanOp& scan, Uint32 accLockOp);
void releaseScanOp(ScanOpPtr& scanPtr);
// for md5 of key (could maybe reuse existing temp buffer)
Uint64 c_dataBuffer[ZWORDS_ON_PAGE/2 + 1];
struct Page_request struct Page_request
{ {
@ -410,6 +487,7 @@ typedef Ptr<Fragoperrec> FragoperrecPtr;
struct Extent_info : public Extent_list_t struct Extent_info : public Extent_list_t
{ {
Uint32 m_first_page_no;
Local_key m_key; Local_key m_key;
Uint32 m_free_space; Uint32 m_free_space;
Uint32 m_free_matrix_pos; Uint32 m_free_matrix_pos;
@ -440,6 +518,7 @@ typedef Ptr<Fragoperrec> FragoperrecPtr;
Disk_alloc_info() {} Disk_alloc_info() {}
Disk_alloc_info(const Tablerec* tabPtrP, Disk_alloc_info(const Tablerec* tabPtrP,
Uint32 extent_size_in_pages); Uint32 extent_size_in_pages);
Uint32 m_extent_size;
/** /**
* Disk allocation * Disk allocation
@ -510,16 +589,17 @@ struct Fragrecord {
Uint32 currentPageRange; Uint32 currentPageRange;
Uint32 rootPageRange; Uint32 rootPageRange;
Uint32 noOfPages; Uint32 noOfPages;
Uint32 emptyPrimPage; DLList<Page>::Head emptyPrimPage; // allocated pages (not init)
DLList<Page>::Head thFreeFirst; // pages with atleast 1 free record
SLList<Page>::Head m_empty_pages; // Empty pages not in logical/physical map
Uint32 thFreeFirst;
Uint32 m_lcp_scan_op; Uint32 m_lcp_scan_op;
State fragStatus; State fragStatus;
Uint32 fragTableId; Uint32 fragTableId;
Uint32 fragmentId; Uint32 fragmentId;
Uint32 nextfreefrag; Uint32 nextfreefrag;
Uint32 free_var_page_array[MAX_FREE_LIST]; DLList<Page>::Head free_var_page_array[MAX_FREE_LIST];
DLList<ScanOp>::Head m_scanList; DLList<ScanOp>::Head m_scanList;
@ -530,11 +610,6 @@ struct Fragrecord {
}; };
typedef Ptr<Fragrecord> FragrecordPtr; typedef Ptr<Fragrecord> FragrecordPtr;
void scanFirst(Signal* signal, Fragrecord*, ScanOpPtr scanPtr);
void scanNext(Signal* signal, Fragrecord*, ScanOpPtr scanPtr);
void scanClose(Signal* signal, ScanOpPtr scanPtr);
void releaseScanOp(ScanOpPtr& scanPtr);
struct Operationrec { struct Operationrec {
/* /*
@ -796,7 +871,12 @@ ArrayPool<TupTriggerData> c_triggerPool;
Uint32 tabDescriptor; Uint32 tabDescriptor;
Uint32 m_real_order_descriptor; Uint32 m_real_order_descriptor;
bool checksumIndicator; enum Bits
{
TR_Checksum = 0x1, // Need to be 1
TR_RowGCI = 0x2
};
Uint16 m_bits;
Uint16 total_rec_size; // Max total size for entire tuple in words Uint16 total_rec_size; // Max total size for entire tuple in words
/** /**
@ -1138,6 +1218,16 @@ typedef Ptr<HostBuffer> HostBufferPtr;
const Uint32* get_disk_ref_ptr(const Tablerec* tabPtrP) const { const Uint32* get_disk_ref_ptr(const Tablerec* tabPtrP) const {
return m_data + tabPtrP->m_offsets[MM].m_disk_ref_offset; return m_data + tabPtrP->m_offsets[MM].m_disk_ref_offset;
} }
Uint32 *get_mm_gci(const Tablerec* tabPtrP){
assert(tabPtrP->m_bits & Tablerec::TR_RowGCI);
return m_data + (tabPtrP->m_bits & Tablerec::TR_Checksum);
}
Uint32 *get_dd_gci(const Tablerec* tabPtrP, Uint32 mm){
assert(tabPtrP->m_bits & Tablerec::TR_RowGCI);
return m_data;
}
}; };
struct KeyReqStruct { struct KeyReqStruct {
@ -1179,13 +1269,15 @@ struct KeyReqStruct {
} m_var_data[2]; } m_var_data[2];
Tuple_header *m_disk_ptr; Tuple_header *m_disk_ptr;
Page* m_page_ptr_p; PagePtr m_page_ptr;
Var_page* m_varpart_page_ptr_p;// could be same as m_page_ptr_p PagePtr m_varpart_page_ptr; // could be same as m_page_ptr_p
PagePtr m_disk_page_ptr; // PagePtr m_disk_page_ptr; //
Local_key m_row_id;
bool dirty_op; bool dirty_op;
bool interpreted_exec; bool interpreted_exec;
bool last_row; bool last_row;
bool m_use_rowid;
Signal* signal; Signal* signal;
Uint32 no_fired_triggers; Uint32 no_fired_triggers;
@ -1290,8 +1382,17 @@ public:
int load_diskpage_scan(Signal*, Uint32 opRec, Uint32 fragPtrI, int load_diskpage_scan(Signal*, Uint32 opRec, Uint32 fragPtrI,
Uint32 local_key, Uint32 flags); Uint32 local_key, Uint32 flags);
int alloc_page(Tablerec*, Fragrecord*, PagePtr*,Uint32 page_no);
void start_restore_lcp(Uint32 tableId, Uint32 fragmentId); void start_restore_lcp(Uint32 tableId, Uint32 fragmentId);
void complete_restore_lcp(Uint32 tableId, Uint32 fragmentId); void complete_restore_lcp(Uint32 tableId, Uint32 fragmentId);
int nr_read_pk(Uint32 fragPtr, const Local_key*, Uint32* dataOut, bool&copy);
int nr_update_gci(Uint32 fragPtr, const Local_key*, Uint32 gci);
int nr_delete(Signal*, Uint32, Uint32 fragPtr, const Local_key*, Uint32 gci);
void nr_delete_page_callback(Signal*, Uint32 op, Uint32 page);
void nr_delete_logbuffer_callback(Signal*, Uint32 op, Uint32 page);
private: private:
BLOCK_DEFINES(Dbtup); BLOCK_DEFINES(Dbtup);
@ -1333,6 +1434,9 @@ private:
void execACC_SCANREQ(Signal* signal); void execACC_SCANREQ(Signal* signal);
void execNEXT_SCANREQ(Signal* signal); void execNEXT_SCANREQ(Signal* signal);
void execACC_CHECK_SCAN(Signal* signal); void execACC_CHECK_SCAN(Signal* signal);
void execACCKEYCONF(Signal* signal);
void execACCKEYREF(Signal* signal);
void execACC_ABORTCONF(Signal* signal);
//------------------------------------------------------------------ //------------------------------------------------------------------
//------------------------------------------------------------------ //------------------------------------------------------------------
@ -1542,7 +1646,7 @@ private:
void handleATTRINFOforTUPKEYREQ(Signal* signal, void handleATTRINFOforTUPKEYREQ(Signal* signal,
const Uint32* data, const Uint32* data,
Uint32 length, Uint32 length,
Operationrec * const regOperPtr); Operationrec * regOperPtr);
// ***************************************************************** // *****************************************************************
// Setting up the environment for reads, inserts, updates and deletes. // Setting up the environment for reads, inserts, updates and deletes.
@ -1550,16 +1654,16 @@ private:
//------------------------------------------------------------------ //------------------------------------------------------------------
//------------------------------------------------------------------ //------------------------------------------------------------------
int handleReadReq(Signal* signal, int handleReadReq(Signal* signal,
Operationrec* const regOperPtr, Operationrec* regOperPtr,
Tablerec* const regTabPtr, Tablerec* regTabPtr,
KeyReqStruct* req_struct); KeyReqStruct* req_struct);
//------------------------------------------------------------------ //------------------------------------------------------------------
//------------------------------------------------------------------ //------------------------------------------------------------------
int handleUpdateReq(Signal* signal, int handleUpdateReq(Signal* signal,
Operationrec* const regOperPtr, Operationrec* regOperPtr,
Fragrecord* const regFragPtr, Fragrecord* regFragPtr,
Tablerec* const regTabPtr, Tablerec* regTabPtr,
KeyReqStruct* req_struct, KeyReqStruct* req_struct,
bool disk); bool disk);
@ -1568,23 +1672,23 @@ private:
int handleInsertReq(Signal* signal, int handleInsertReq(Signal* signal,
Ptr<Operationrec> regOperPtr, Ptr<Operationrec> regOperPtr,
Ptr<Fragrecord>, Ptr<Fragrecord>,
Tablerec* const regTabPtr, Tablerec* regTabPtr,
KeyReqStruct* req_struct); KeyReqStruct* req_struct);
//------------------------------------------------------------------ //------------------------------------------------------------------
//------------------------------------------------------------------ //------------------------------------------------------------------
int handleDeleteReq(Signal* signal, int handleDeleteReq(Signal* signal,
Operationrec* const regOperPtr, Operationrec* regOperPtr,
Fragrecord* const regFragPtr, Fragrecord* regFragPtr,
Tablerec* const regTabPtr, Tablerec* regTabPtr,
KeyReqStruct* req_struct); KeyReqStruct* req_struct);
//------------------------------------------------------------------ //------------------------------------------------------------------
//------------------------------------------------------------------ //------------------------------------------------------------------
int updateStartLab(Signal* signal, int updateStartLab(Signal* signal,
Operationrec* const regOperPtr, Operationrec* regOperPtr,
Fragrecord* const regFragPtr, Fragrecord* regFragPtr,
Tablerec* const regTabPtr, Tablerec* regTabPtr,
KeyReqStruct* req_struct); KeyReqStruct* req_struct);
// ***************************************************************** // *****************************************************************
@ -1616,19 +1720,19 @@ private:
void sendReadAttrinfo(Signal* signal, void sendReadAttrinfo(Signal* signal,
KeyReqStruct *req_struct, KeyReqStruct *req_struct,
Uint32 TnoOfData, Uint32 TnoOfData,
const Operationrec * const regOperPtr); const Operationrec * regOperPtr);
//------------------------------------------------------------------ //------------------------------------------------------------------
//------------------------------------------------------------------ //------------------------------------------------------------------
void sendLogAttrinfo(Signal* signal, void sendLogAttrinfo(Signal* signal,
Uint32 TlogSize, Uint32 TlogSize,
Operationrec * const regOperPtr); Operationrec * regOperPtr);
//------------------------------------------------------------------ //------------------------------------------------------------------
//------------------------------------------------------------------ //------------------------------------------------------------------
void sendTUPKEYCONF(Signal* signal, void sendTUPKEYCONF(Signal* signal,
KeyReqStruct *req_struct, KeyReqStruct *req_struct,
Operationrec * const regOperPtr); Operationrec * regOperPtr);
//------------------------------------------------------------------ //------------------------------------------------------------------
//------------------------------------------------------------------ //------------------------------------------------------------------
@ -1843,7 +1947,7 @@ private:
//------------------------------------------------------------------ //------------------------------------------------------------------
//------------------------------------------------------------------ //------------------------------------------------------------------
void setUpQueryRoutines(Tablerec* const regTabPtr); void setUpQueryRoutines(Tablerec* regTabPtr);
// ***************************************************************** // *****************************************************************
// Service methods. // Service methods.
@ -1863,7 +1967,7 @@ private:
//------------------------------------------------------------------ //------------------------------------------------------------------
//------------------------------------------------------------------ //------------------------------------------------------------------
void copyAttrinfo(Operationrec * const regOperPtr, Uint32* inBuffer); void copyAttrinfo(Operationrec * regOperPtr, Uint32* inBuffer);
//------------------------------------------------------------------ //------------------------------------------------------------------
//------------------------------------------------------------------ //------------------------------------------------------------------
@ -1875,7 +1979,7 @@ private:
//------------------------------------------------------------------ //------------------------------------------------------------------
//------------------------------------------------------------------ //------------------------------------------------------------------
int initStoredOperationrec(Operationrec* const regOperPtr, int initStoredOperationrec(Operationrec* regOperPtr,
KeyReqStruct* req_struct, KeyReqStruct* req_struct,
Uint32 storedId); Uint32 storedId);
@ -1905,57 +2009,57 @@ private:
void void
checkImmediateTriggersAfterInsert(KeyReqStruct *req_struct, checkImmediateTriggersAfterInsert(KeyReqStruct *req_struct,
Operationrec* const regOperPtr, Operationrec* regOperPtr,
Tablerec* const tablePtr); Tablerec* tablePtr);
void void
checkImmediateTriggersAfterUpdate(KeyReqStruct *req_struct, checkImmediateTriggersAfterUpdate(KeyReqStruct *req_struct,
Operationrec* const regOperPtr, Operationrec* regOperPtr,
Tablerec* const tablePtr); Tablerec* tablePtr);
void void
checkImmediateTriggersAfterDelete(KeyReqStruct *req_struct, checkImmediateTriggersAfterDelete(KeyReqStruct *req_struct,
Operationrec* const regOperPtr, Operationrec* regOperPtr,
Tablerec* const tablePtr); Tablerec* tablePtr);
#if 0 #if 0
void checkDeferredTriggers(Signal* signal, void checkDeferredTriggers(Signal* signal,
Operationrec* const regOperPtr, Operationrec* regOperPtr,
Tablerec* const regTablePtr); Tablerec* regTablePtr);
#endif #endif
void checkDetachedTriggers(KeyReqStruct *req_struct, void checkDetachedTriggers(KeyReqStruct *req_struct,
Operationrec* const regOperPtr, Operationrec* regOperPtr,
Tablerec* const regTablePtr); Tablerec* regTablePtr);
void fireImmediateTriggers(KeyReqStruct *req_struct, void fireImmediateTriggers(KeyReqStruct *req_struct,
ArrayList<TupTriggerData>& triggerList, ArrayList<TupTriggerData>& triggerList,
Operationrec* const regOperPtr); Operationrec* regOperPtr);
void fireDeferredTriggers(KeyReqStruct *req_struct, void fireDeferredTriggers(KeyReqStruct *req_struct,
ArrayList<TupTriggerData>& triggerList, ArrayList<TupTriggerData>& triggerList,
Operationrec* const regOperPtr); Operationrec* regOperPtr);
void fireDetachedTriggers(KeyReqStruct *req_struct, void fireDetachedTriggers(KeyReqStruct *req_struct,
ArrayList<TupTriggerData>& triggerList, ArrayList<TupTriggerData>& triggerList,
Operationrec* const regOperPtr); Operationrec* regOperPtr);
void executeTriggers(KeyReqStruct *req_struct, void executeTriggers(KeyReqStruct *req_struct,
ArrayList<TupTriggerData>& triggerList, ArrayList<TupTriggerData>& triggerList,
Operationrec* const regOperPtr); Operationrec* regOperPtr);
void executeTrigger(KeyReqStruct *req_struct, void executeTrigger(KeyReqStruct *req_struct,
TupTriggerData* const trigPtr, TupTriggerData* trigPtr,
Operationrec* const regOperPtr); Operationrec* regOperPtr);
bool readTriggerInfo(TupTriggerData* const trigPtr, bool readTriggerInfo(TupTriggerData* trigPtr,
Operationrec* const regOperPtr, Operationrec* regOperPtr,
KeyReqStruct * const req_struct, KeyReqStruct * req_struct,
Fragrecord* const regFragPtr, Fragrecord* regFragPtr,
Uint32* const keyBuffer, Uint32* keyBuffer,
Uint32& noPrimKey, Uint32& noPrimKey,
Uint32* const afterBuffer, Uint32* afterBuffer,
Uint32& noAfterWords, Uint32& noAfterWords,
Uint32* const beforeBuffer, Uint32* beforeBuffer,
Uint32& noBeforeWords); Uint32& noBeforeWords);
void sendTrigAttrInfo(Signal* signal, void sendTrigAttrInfo(Signal* signal,
@ -1970,8 +2074,8 @@ private:
void sendFireTrigOrd(Signal* signal, void sendFireTrigOrd(Signal* signal,
KeyReqStruct *req_struct, KeyReqStruct *req_struct,
Operationrec * const regOperPtr, Operationrec * regOperPtr,
TupTriggerData* const trigPtr, TupTriggerData* trigPtr,
Uint32 fragmentId, Uint32 fragmentId,
Uint32 noPrimKeySignals, Uint32 noPrimKeySignals,
Uint32 noBeforeSignals, Uint32 noBeforeSignals,
@ -1982,19 +2086,19 @@ private:
// these set terrorCode and return non-zero on error // these set terrorCode and return non-zero on error
int executeTuxInsertTriggers(Signal* signal, int executeTuxInsertTriggers(Signal* signal,
Operationrec* const regOperPtr, Operationrec* regOperPtr,
Fragrecord* const regFragPtr, Fragrecord* regFragPtr,
Tablerec* const regTabPtr); Tablerec* regTabPtr);
int executeTuxUpdateTriggers(Signal* signal, int executeTuxUpdateTriggers(Signal* signal,
Operationrec* const regOperPtr, Operationrec* regOperPtr,
Fragrecord* const regFragPtr, Fragrecord* regFragPtr,
Tablerec* const regTabPtr); Tablerec* regTabPtr);
int executeTuxDeleteTriggers(Signal* signal, int executeTuxDeleteTriggers(Signal* signal,
Operationrec* const regOperPtr, Operationrec* regOperPtr,
Fragrecord* const regFragPtr, Fragrecord* regFragPtr,
Tablerec* const regTabPtr); Tablerec* regTabPtr);
int addTuxEntries(Signal* signal, int addTuxEntries(Signal* signal,
Operationrec* regOperPtr, Operationrec* regOperPtr,
@ -2004,16 +2108,15 @@ private:
void executeTuxCommitTriggers(Signal* signal, void executeTuxCommitTriggers(Signal* signal,
Operationrec* regOperPtr, Operationrec* regOperPtr,
Fragrecord* const regFragPtr, Fragrecord* regFragPtr,
Tablerec* const regTabPtr); Tablerec* regTabPtr);
void executeTuxAbortTriggers(Signal* signal, void executeTuxAbortTriggers(Signal* signal,
Operationrec* regOperPtr, Operationrec* regOperPtr,
Fragrecord* const regFragPtr, Fragrecord* regFragPtr,
Tablerec* const regTabPtr); Tablerec* regTabPtr);
void removeTuxEntries(Signal* signal, void removeTuxEntries(Signal* signal,
Operationrec* regOperPtr,
Tablerec* regTabPtr); Tablerec* regTabPtr);
// ***************************************************************** // *****************************************************************
@ -2092,7 +2195,7 @@ private:
//------------------------------------------------------------------ //------------------------------------------------------------------
#if 0 #if 0
void checkPages(Fragrecord* const regFragPtr); void checkPages(Fragrecord* regFragPtr);
#endif #endif
Uint32 convert_byte_to_word_size(Uint32 byte_size) Uint32 convert_byte_to_word_size(Uint32 byte_size)
{ {
@ -2106,59 +2209,53 @@ private:
void prepare_initial_insert(KeyReqStruct*, Operationrec*, Tablerec*); void prepare_initial_insert(KeyReqStruct*, Operationrec*, Tablerec*);
void fix_disk_insert_no_mem_insert(KeyReqStruct*, Operationrec*, Tablerec*); void fix_disk_insert_no_mem_insert(KeyReqStruct*, Operationrec*, Tablerec*);
void setup_fixed_part(KeyReqStruct* req_struct, void setup_fixed_part(KeyReqStruct* req_struct,
Operationrec* const regOperPtr, Operationrec* regOperPtr,
Tablerec* const regTabPtr); Tablerec* regTabPtr);
void send_TUPKEYREF(Signal* signal, void send_TUPKEYREF(Signal* signal,
Operationrec* const regOperPtr); Operationrec* regOperPtr);
void early_tupkey_error(Signal* signal); void early_tupkey_error(Signal* signal);
void printoutTuplePage(Uint32 fragid, Uint32 pageid, Uint32 printLimit); void printoutTuplePage(Uint32 fragid, Uint32 pageid, Uint32 printLimit);
bool checkUpdateOfPrimaryKey(KeyReqStruct *req_struct, bool checkUpdateOfPrimaryKey(KeyReqStruct *req_struct,
Uint32* updateBuffer, Uint32* updateBuffer,
Tablerec* const regTabPtr); Tablerec* regTabPtr);
void setNullBits(Uint32*, Tablerec* const regTabPtr); void setNullBits(Uint32*, Tablerec* regTabPtr);
bool checkNullAttributes(KeyReqStruct * const, Tablerec* const); bool checkNullAttributes(KeyReqStruct * const, Tablerec* const);
bool setup_read(KeyReqStruct* req_struct, bool setup_read(KeyReqStruct* req_struct,
Operationrec* const regOperPtr, Operationrec* regOperPtr,
Fragrecord* const regFragPtr, Fragrecord* regFragPtr,
Tablerec* const regTabPtr, Tablerec* regTabPtr,
bool disk); bool disk);
bool getPageLastCommitted(Operationrec* const regOperPtr, Uint32 calculateChecksum(Tuple_header*, Tablerec* regTabPtr);
Operationrec* const leaderOpPtr); void setChecksum(Tuple_header*, Tablerec* regTabPtr);
bool getPageThroughSavePoint(Operationrec* const regOperPtr,
Operationrec* const leaderOpPtr);
Uint32 calculateChecksum(Tuple_header*, Tablerec* const regTabPtr);
void setChecksum(Tuple_header*, Tablerec* const regTabPtr);
void complexTrigger(Signal* signal, void complexTrigger(Signal* signal,
KeyReqStruct *req_struct, KeyReqStruct *req_struct,
Operationrec* const regOperPtr, Operationrec* regOperPtr,
Fragrecord* const regFragPtr, Fragrecord* regFragPtr,
Tablerec* const regTabPtr); Tablerec* regTabPtr);
void setTupleStatesSetOpType(Operationrec* const regOperPtr, void setTupleStatesSetOpType(Operationrec* regOperPtr,
KeyReqStruct *req_struct, KeyReqStruct *req_struct,
Page* const pagePtr, Page* pagePtr,
Uint32& opType, Uint32& opType,
OperationrecPtr& firstOpPtr); OperationrecPtr& firstOpPtr);
void findBeforeValueOperation(OperationrecPtr& befOpPtr, void findBeforeValueOperation(OperationrecPtr& befOpPtr,
OperationrecPtr firstOpPtr); OperationrecPtr firstOpPtr);
void calculateChangeMask(Page* const PagePtr, void calculateChangeMask(Page* PagePtr,
Tablerec* const regTabPtr, Tablerec* regTabPtr,
KeyReqStruct * const req_struct); KeyReqStruct * req_struct);
void updateGcpId(KeyReqStruct *req_struct, void updateGcpId(KeyReqStruct *req_struct,
Operationrec* const regOperPtr, Operationrec* regOperPtr,
Fragrecord* const regFragPtr, Fragrecord* regFragPtr,
Tablerec* const regTabPtr); Tablerec* regTabPtr);
void setTupleStateOnPreviousOps(Uint32 prevOpIndex); void setTupleStateOnPreviousOps(Uint32 prevOpIndex);
void copyMem(Signal* signal, Uint32 sourceIndex, Uint32 destIndex); void copyMem(Signal* signal, Uint32 sourceIndex, Uint32 destIndex);
@ -2170,14 +2267,14 @@ private:
void updatePackedList(Signal* signal, Uint16 ahostIndex); void updatePackedList(Signal* signal, Uint16 ahostIndex);
void setUpDescriptorReferences(Uint32 descriptorReference, void setUpDescriptorReferences(Uint32 descriptorReference,
Tablerec* const regTabPtr, Tablerec* regTabPtr,
const Uint32* offset); const Uint32* offset);
void setUpKeyArray(Tablerec* const regTabPtr); void setUpKeyArray(Tablerec* regTabPtr);
bool addfragtotab(Tablerec* const regTabPtr, Uint32 fragId, Uint32 fragIndex); bool addfragtotab(Tablerec* regTabPtr, Uint32 fragId, Uint32 fragIndex);
void deleteFragTab(Tablerec* const regTabPtr, Uint32 fragId); void deleteFragTab(Tablerec* regTabPtr, Uint32 fragId);
void abortAddFragOp(Signal* signal); void abortAddFragOp(Signal* signal);
void releaseTabDescr(Tablerec* const regTabPtr); void releaseTabDescr(Tablerec* regTabPtr);
void getFragmentrec(FragrecordPtr& regFragPtr, Uint32 fragId, Tablerec* const regTabPtr); void getFragmentrec(FragrecordPtr& regFragPtr, Uint32 fragId, Tablerec* regTabPtr);
void initialiseRecordsLab(Signal* signal, Uint32 switchData, Uint32, Uint32); void initialiseRecordsLab(Signal* signal, Uint32 switchData, Uint32, Uint32);
void initializeAttrbufrec(); void initializeAttrbufrec();
@ -2194,7 +2291,7 @@ private:
void initializeTabDescr(); void initializeTabDescr();
void initializeUndoPage(); void initializeUndoPage();
void initTab(Tablerec* const regTabPtr); void initTab(Tablerec* regTabPtr);
void startphase3Lab(Signal* signal, Uint32 config1, Uint32 config2); void startphase3Lab(Signal* signal, Uint32 config1, Uint32 config2);
@ -2204,17 +2301,17 @@ private:
void fragrefuse3Lab(Signal* signal, void fragrefuse3Lab(Signal* signal,
FragoperrecPtr fragOperPtr, FragoperrecPtr fragOperPtr,
FragrecordPtr regFragPtr, FragrecordPtr regFragPtr,
Tablerec* const regTabPtr, Tablerec* regTabPtr,
Uint32 fragId); Uint32 fragId);
void fragrefuse4Lab(Signal* signal, void fragrefuse4Lab(Signal* signal,
FragoperrecPtr fragOperPtr, FragoperrecPtr fragOperPtr,
FragrecordPtr regFragPtr, FragrecordPtr regFragPtr,
Tablerec* const regTabPtr, Tablerec* regTabPtr,
Uint32 fragId); Uint32 fragId);
void addattrrefuseLab(Signal* signal, void addattrrefuseLab(Signal* signal,
FragrecordPtr regFragPtr, FragrecordPtr regFragPtr,
FragoperrecPtr fragOperPtr, FragoperrecPtr fragOperPtr,
Tablerec* const regTabPtr, Tablerec* regTabPtr,
Uint32 fragId); Uint32 fragId);
@ -2291,24 +2388,25 @@ private:
//------------------------------------------------------------------------------------------------------ //------------------------------------------------------------------------------------------------------
// //
// Public methods // Public methods
Uint32 getRealpid(Fragrecord* const regFragPtr, Uint32 logicalPageId); Uint32 getRealpid(Fragrecord* regFragPtr, Uint32 logicalPageId);
Uint32 getNoOfPages(Fragrecord* const regFragPtr); Uint32 getNoOfPages(Fragrecord* regFragPtr);
void initPageRangeSize(Uint32 size); void initPageRangeSize(Uint32 size);
bool insertPageRangeTab(Fragrecord* const regFragPtr, bool insertPageRangeTab(Fragrecord* regFragPtr,
Uint32 startPageId, Uint32 startPageId,
Uint32 noPages); Uint32 noPages);
void releaseFragPages(Fragrecord* const regFragPtr); void releaseFragPages(Fragrecord* regFragPtr);
void initFragRange(Fragrecord* const regFragPtr); void initFragRange(Fragrecord* regFragPtr);
void initializePageRange(); void initializePageRange();
Uint32 getEmptyPage(Fragrecord* const regFragPtr); Uint32 getEmptyPage(Fragrecord* regFragPtr);
Uint32 allocFragPages(Fragrecord* const regFragPtr, Uint32 noOfPagesAllocated); Uint32 allocFragPages(Fragrecord* regFragPtr, Uint32 noOfPagesAllocated);
Uint32 get_empty_var_page(Fragrecord* frag_ptr);
// Private methods // Private methods
Uint32 leafPageRangeFull(Fragrecord* const regFragPtr, PageRangePtr currPageRangePtr); Uint32 leafPageRangeFull(Fragrecord* regFragPtr, PageRangePtr currPageRangePtr);
void releasePagerange(PageRangePtr regPRPtr); void releasePagerange(PageRangePtr regPRPtr);
void seizePagerange(PageRangePtr& regPageRangePtr); void seizePagerange(PageRangePtr& regPageRangePtr);
void errorHandler(Uint32 errorCode); void errorHandler(Uint32 errorCode);
void allocMoreFragPages(Fragrecord* const regFragPtr); void allocMoreFragPages(Fragrecord* regFragPtr);
// Private data // Private data
Uint32 cfirstfreerange; Uint32 cfirstfreerange;
@ -2328,7 +2426,7 @@ private:
// Private methods // Private methods
Uint32 get_alloc_page(Fragrecord* const, Uint32); Uint32 get_alloc_page(Fragrecord* const, Uint32);
void update_free_page_list(Fragrecord* const, Var_page*); void update_free_page_list(Fragrecord* const, Ptr<Page>);
#if 0 #if 0
Uint32 calc_free_list(const Tablerec* regTabPtr, Uint32 sz) const { Uint32 calc_free_list(const Tablerec* regTabPtr, Uint32 sz) const {
@ -2346,10 +2444,11 @@ private:
//--------------------------------------------------------------- //---------------------------------------------------------------
// //
// Public methods // Public methods
Uint32* alloc_var_rec(Fragrecord*const, Tablerec*const, Uint32, Local_key*, Uint32* alloc_var_rec(Fragrecord*, Tablerec*, Uint32, Local_key*, Uint32*);
Uint32*, Uint32 base); void free_var_rec(Fragrecord*, Tablerec*, Local_key*, Ptr<Page>);
void free_var_part(Fragrecord*, Tablerec*, Var_part_ref, Uint32 chain); Uint32* alloc_var_part(Fragrecord*, Tablerec*, Uint32, Local_key*);
void free_var_part(Fragrecord*, Tablerec*, Local_key*, Var_page*, Uint32 chain); int realloc_var_part(Fragrecord*, Tablerec*,
PagePtr, Var_part_ref*, Uint32, Uint32);
void validate_page(Tablerec*, Var_page* page); void validate_page(Tablerec*, Var_page* page);
@ -2357,15 +2456,18 @@ private:
Uint32*); Uint32*);
void free_fix_rec(Fragrecord*, Tablerec*, Local_key*, Fix_page*); void free_fix_rec(Fragrecord*, Tablerec*, Local_key*, Fix_page*);
Uint32* alloc_fix_rowid(Fragrecord*, Tablerec*, Local_key*, Uint32 *);
Uint32* alloc_var_rowid(Fragrecord*, Tablerec*, Uint32, Local_key*, Uint32*);
// Private methods // Private methods
void convertThPage(Uint32 Tupheadsize, void convertThPage(Fix_page* regPagePtr,
Fix_page* const regPagePtr); Tablerec*,
Uint32 mm);
/** /**
* Return offset * Return offset
*/ */
Uint32 alloc_tuple_from_page(Fragrecord* const regFragPtr, Uint32 alloc_tuple_from_page(Fragrecord* regFragPtr,
Fix_page* const regPagePtr); Fix_page* regPagePtr);
//--------------------------------------------------------------- //---------------------------------------------------------------
// Temporary variables used for storing commonly used variables // Temporary variables used for storing commonly used variables
@ -2398,8 +2500,7 @@ private:
ArrayPool<Operationrec> c_operation_pool; ArrayPool<Operationrec> c_operation_pool;
Page *cpage; ArrayPool<Page> c_page_pool;
Uint32 cnoOfPage;
Uint32 cnoOfAllocatedPages; Uint32 cnoOfAllocatedPages;
Tablerec *tablerec; Tablerec *tablerec;
@ -2437,9 +2538,6 @@ private:
// Trigger variables // Trigger variables
Uint32 c_maxTriggersPerTable; Uint32 c_maxTriggersPerTable;
STATIC_CONST(MAX_PARALLELL_TUP_SRREQ = 2);
Uint32 c_sr_free_page_0;
Uint32 c_errorInsert4000TableId; Uint32 c_errorInsert4000TableId;
Uint32 c_min_list_size[MAX_FREE_LIST + 1]; Uint32 c_min_list_size[MAX_FREE_LIST + 1];
Uint32 c_max_list_size[MAX_FREE_LIST + 1]; Uint32 c_max_list_size[MAX_FREE_LIST + 1];
@ -2462,9 +2560,9 @@ private:
bool disk); bool disk);
Uint32* get_ptr(Var_part_ref); Uint32* get_ptr(Var_part_ref);
Uint32* get_ptr(Ptr<Var_page>*, Var_part_ref); Uint32* get_ptr(PagePtr*, Var_part_ref);
Uint32* get_ptr(PagePtr*, const Local_key*, const Tablerec*); Uint32* get_ptr(PagePtr*, const Local_key*, const Tablerec*);
Uint32* get_ptr(PagePtr*, const Local_key*, const Tablerec*, Uint32 mm); Uint32* get_dd_ptr(PagePtr*, const Local_key*, const Tablerec*);
/** /**
* prealloc space from disk * prealloc space from disk
@ -2561,7 +2659,7 @@ private:
#endif #endif
void fix_commit_order(OperationrecPtr); void fix_commit_order(OperationrecPtr);
void commit_operation(Signal*, Uint32, Tuple_header*, Page*, void commit_operation(Signal*, Uint32, Tuple_header*, PagePtr,
Operationrec*, Fragrecord*, Tablerec*); Operationrec*, Fragrecord*, Tablerec*);
void dealloc_tuple(Signal* signal, Uint32, Page*, Tuple_header*, void dealloc_tuple(Signal* signal, Uint32, Page*, Tuple_header*,
@ -2570,8 +2668,8 @@ private:
int handle_size_change_after_update(KeyReqStruct* req_struct, int handle_size_change_after_update(KeyReqStruct* req_struct,
Tuple_header* org, Tuple_header* org,
Operationrec*, Operationrec*,
Fragrecord* const regFragPtr, Fragrecord* regFragPtr,
Tablerec* const regTabPtr, Tablerec* regTabPtr,
Uint32 sizes[4]); Uint32 sizes[4]);
/** /**
@ -2581,6 +2679,7 @@ private:
void prepare_read(KeyReqStruct*, Tablerec* const, bool disk); void prepare_read(KeyReqStruct*, Tablerec* const, bool disk);
}; };
#if 0
inline inline
Uint32 Uint32
Dbtup::get_frag_page_id(Uint32 real_page_id) Dbtup::get_frag_page_id(Uint32 real_page_id)
@ -2590,17 +2689,18 @@ Dbtup::get_frag_page_id(Uint32 real_page_id)
ptrCheckGuard(real_page_ptr, cnoOfPage, cpage); ptrCheckGuard(real_page_ptr, cnoOfPage, cpage);
return real_page_ptr.p->frag_page_id; return real_page_ptr.p->frag_page_id;
} }
#endif
inline inline
Dbtup::TransState Dbtup::TransState
Dbtup::get_trans_state(Operationrec * const regOperPtr) Dbtup::get_trans_state(Operationrec * regOperPtr)
{ {
return (Dbtup::TransState)regOperPtr->op_struct.trans_state; return (Dbtup::TransState)regOperPtr->op_struct.trans_state;
} }
inline inline
void void
Dbtup::set_trans_state(Operationrec* const regOperPtr, Dbtup::set_trans_state(Operationrec* regOperPtr,
Dbtup::TransState trans_state) Dbtup::TransState trans_state)
{ {
regOperPtr->op_struct.trans_state= (Uint32)trans_state; regOperPtr->op_struct.trans_state= (Uint32)trans_state;
@ -2608,14 +2708,14 @@ Dbtup::set_trans_state(Operationrec* const regOperPtr,
inline inline
Dbtup::TupleState Dbtup::TupleState
Dbtup::get_tuple_state(Operationrec * const regOperPtr) Dbtup::get_tuple_state(Operationrec * regOperPtr)
{ {
return (Dbtup::TupleState)regOperPtr->op_struct.tuple_state; return (Dbtup::TupleState)regOperPtr->op_struct.tuple_state;
} }
inline inline
void void
Dbtup::set_tuple_state(Operationrec* const regOperPtr, Dbtup::set_tuple_state(Operationrec* regOperPtr,
Dbtup::TupleState tuple_state) Dbtup::TupleState tuple_state)
{ {
regOperPtr->op_struct.tuple_state= (Uint32)tuple_state; regOperPtr->op_struct.tuple_state= (Uint32)tuple_state;
@ -2631,14 +2731,14 @@ Dbtup::decr_tup_version(Uint32 tup_version)
inline inline
Dbtup::ChangeMaskState Dbtup::ChangeMaskState
Dbtup::get_change_mask_state(Operationrec * const regOperPtr) Dbtup::get_change_mask_state(Operationrec * regOperPtr)
{ {
return (Dbtup::ChangeMaskState)regOperPtr->op_struct.change_mask_state; return (Dbtup::ChangeMaskState)regOperPtr->op_struct.change_mask_state;
} }
inline inline
void void
Dbtup::set_change_mask_state(Operationrec * const regOperPtr, Dbtup::set_change_mask_state(Operationrec * regOperPtr,
ChangeMaskState new_state) ChangeMaskState new_state)
{ {
regOperPtr->op_struct.change_mask_state= (Uint32)new_state; regOperPtr->op_struct.change_mask_state= (Uint32)new_state;
@ -2646,8 +2746,8 @@ Dbtup::set_change_mask_state(Operationrec * const regOperPtr,
inline inline
void void
Dbtup::update_change_mask_info(KeyReqStruct * const req_struct, Dbtup::update_change_mask_info(KeyReqStruct * req_struct,
Operationrec * const regOperPtr) Operationrec * regOperPtr)
{ {
//Save change mask //Save change mask
if (req_struct->max_attr_id_updated == 0) { if (req_struct->max_attr_id_updated == 0) {
@ -2667,19 +2767,19 @@ inline
Uint32* Uint32*
Dbtup::get_ptr(Var_part_ref ref) Dbtup::get_ptr(Var_part_ref ref)
{ {
Ptr<Var_page> tmp; Ptr<Page> tmp;
return get_ptr(&tmp, ref); return get_ptr(&tmp, ref);
} }
inline inline
Uint32* Uint32*
Dbtup::get_ptr(Ptr<Var_page>* pagePtr, Var_part_ref ref) Dbtup::get_ptr(Ptr<Page>* pagePtr, Var_part_ref ref)
{ {
PagePtr tmp; PagePtr tmp;
Uint32 page_idx= ref.m_ref & MAX_TUPLES_PER_PAGE; Uint32 page_idx= ref.m_ref & MAX_TUPLES_PER_PAGE;
tmp.i= ref.m_ref >> MAX_TUPLES_BITS; tmp.i= ref.m_ref >> MAX_TUPLES_BITS;
ptrCheckGuard(tmp, cnoOfPage, cpage); c_page_pool.getPtr(tmp);
memcpy(pagePtr, &tmp, sizeof(tmp)); memcpy(pagePtr, &tmp, sizeof(tmp));
return ((Var_page*)tmp.p)->get_ptr(page_idx); return ((Var_page*)tmp.p)->get_ptr(page_idx);
} }
@ -2691,38 +2791,28 @@ Dbtup::get_ptr(PagePtr* pagePtr,
{ {
PagePtr tmp; PagePtr tmp;
tmp.i= key->m_page_no; tmp.i= key->m_page_no;
ptrCheckGuard(tmp, cnoOfPage, cpage); c_page_pool.getPtr(tmp);
memcpy(pagePtr, &tmp, sizeof(tmp)); memcpy(pagePtr, &tmp, sizeof(tmp));
if(regTabPtr->m_attributes[MM].m_no_of_varsize)
return ((Var_page*)tmp.p)->get_ptr(key->m_page_idx);
else
return ((Fix_page*)tmp.p)-> return ((Fix_page*)tmp.p)->
get_ptr(key->m_page_idx, regTabPtr->m_offsets[MM].m_fix_header_size); get_ptr(key->m_page_idx, regTabPtr->m_offsets[MM].m_fix_header_size);
} }
inline inline
Uint32* Uint32*
Dbtup::get_ptr(PagePtr* pagePtr, Dbtup::get_dd_ptr(PagePtr* pagePtr,
const Local_key* key, const Tablerec* regTabPtr, Uint32 mm) const Local_key* key, const Tablerec* regTabPtr)
{ {
PagePtr tmp; PagePtr tmp;
tmp.i= key->m_page_no; tmp.i= key->m_page_no;
if(mm == MM)
{
ptrCheckGuard(tmp, cnoOfPage, cpage);
}
else
{
tmp.p= (Page*)m_global_page_pool.getPtr(tmp.i); tmp.p= (Page*)m_global_page_pool.getPtr(tmp.i);
}
memcpy(pagePtr, &tmp, sizeof(tmp)); memcpy(pagePtr, &tmp, sizeof(tmp));
if(regTabPtr->m_attributes[mm].m_no_of_varsize) if(regTabPtr->m_attributes[DD].m_no_of_varsize)
return ((Var_page*)tmp.p)->get_ptr(key->m_page_idx); return ((Var_page*)tmp.p)->get_ptr(key->m_page_idx);
else else
return ((Fix_page*)tmp.p)-> return ((Fix_page*)tmp.p)->
get_ptr(key->m_page_idx, regTabPtr->m_offsets[mm].m_fix_header_size); get_ptr(key->m_page_idx, regTabPtr->m_offsets[DD].m_fix_header_size);
} }
NdbOut& NdbOut&

View File

@ -132,45 +132,48 @@ void Dbtup::execTUP_ABORTREQ(Signal* signal)
disk_page_abort_prealloc(signal, regFragPtr.p, &key, key.m_page_idx); disk_page_abort_prealloc(signal, regFragPtr.p, &key, key.m_page_idx);
} }
Uint32 bits= copy->m_header_bits; Uint32 bits= tuple_ptr->m_header_bits;
Uint32 copy_bits= copy->m_header_bits;
if(! (bits & Tuple_header::ALLOC)) if(! (bits & Tuple_header::ALLOC))
{ {
if(bits & Tuple_header::MM_GROWN) if(copy_bits & Tuple_header::MM_GROWN)
{ {
ndbout_c("abort grow"); ndbout_c("abort grow");
Var_page *pageP= (Var_page*)page.p; Ptr<Page> vpage;
Uint32 idx= regOperPtr.p->m_tuple_location.m_page_idx, sz; Uint32 idx= regOperPtr.p->m_tuple_location.m_page_idx;
Uint32 mm_vars= regTabPtr.p->m_attributes[MM].m_no_of_varsize; Uint32 mm_vars= regTabPtr.p->m_attributes[MM].m_no_of_varsize;
Uint32 *var_part; Uint32 *var_part;
if(! (tuple_ptr->m_header_bits & Tuple_header::CHAINED_ROW))
{ ndbassert(tuple_ptr->m_header_bits & Tuple_header::CHAINED_ROW);
var_part= tuple_ptr->get_var_part_ptr(regTabPtr.p);
sz= Tuple_header::HeaderSize +
regTabPtr.p->m_offsets[MM].m_fix_header_size;
}
else
{
Ptr<Var_page> vpage;
Uint32 ref= * tuple_ptr->get_var_part_ptr(regTabPtr.p); Uint32 ref= * tuple_ptr->get_var_part_ptr(regTabPtr.p);
Local_key tmp; Local_key tmp;
tmp.assref(ref); tmp.assref(ref);
sz= 0;
idx= tmp.m_page_idx; idx= tmp.m_page_idx;
var_part= get_ptr(&vpage, *(Var_part_ref*)&ref); var_part= get_ptr(&vpage, *(Var_part_ref*)&ref);
pageP= vpage.p; Var_page* pageP = (Var_page*)vpage.p;
}
Uint32 len= pageP->get_entry_len(idx) & ~Var_page::CHAIN; Uint32 len= pageP->get_entry_len(idx) & ~Var_page::CHAIN;
sz += ((((mm_vars + 1) << 1) + (((Uint16*)var_part)[mm_vars]) + 3)>> 2); Uint32 sz = ((((mm_vars + 1) << 1) + (((Uint16*)var_part)[mm_vars]) + 3)>> 2);
ndbassert(sz <= len); ndbassert(sz <= len);
pageP->shrink_entry(idx, sz); pageP->shrink_entry(idx, sz);
update_free_page_list(regFragPtr.p, pageP); update_free_page_list(regFragPtr.p, vpage);
} }
else if(bits & Tuple_header::MM_SHRINK) else if(bits & Tuple_header::MM_SHRINK)
{ {
ndbout_c("abort shrink"); ndbout_c("abort shrink");
} }
} }
else if (regOperPtr.p->is_first_operation() &&
regOperPtr.p->is_last_operation())
{
/**
* Aborting last operation that performed ALLOC
*/
ndbout_c("clearing ALLOC");
tuple_ptr->m_header_bits &= ~(Uint32)Tuple_header::ALLOC;
tuple_ptr->m_header_bits |= Tuple_header::FREE;
}
} }
if(regOperPtr.p->is_first_operation() && regOperPtr.p->is_last_operation()) if(regOperPtr.p->is_first_operation() && regOperPtr.p->is_last_operation())
@ -339,8 +342,14 @@ void Dbtup::tupkeyErrorLab(Signal* signal)
regOperPtr->m_undo_buffer_space); regOperPtr->m_undo_buffer_space);
} }
Uint32 *ptr = 0;
if (!regOperPtr->m_tuple_location.isNull())
{
PagePtr tmp; PagePtr tmp;
Uint32 *ptr= get_ptr(&tmp, &regOperPtr->m_tuple_location, tabPtr.p); ptr= get_ptr(&tmp, &regOperPtr->m_tuple_location, tabPtr.p);
}
removeActiveOpList(regOperPtr, (Tuple_header*)ptr); removeActiveOpList(regOperPtr, (Tuple_header*)ptr);
initOpConnection(regOperPtr); initOpConnection(regOperPtr);
send_TUPKEYREF(signal, regOperPtr); send_TUPKEYREF(signal, regOperPtr);

View File

@ -55,14 +55,7 @@ void Dbtup::execTUP_DEALLOCREQ(Signal* signal)
if (regTabPtr.p->m_attributes[MM].m_no_of_varsize) if (regTabPtr.p->m_attributes[MM].m_no_of_varsize)
{ {
ljam(); ljam();
free_var_rec(regFragPtr.p, regTabPtr.p, &tmp, pagePtr);
if(ptr->m_header_bits & Tuple_header::CHAINED_ROW)
{
free_var_part(regFragPtr.p, regTabPtr.p,
*(Var_part_ref*)ptr->get_var_part_ptr(regTabPtr.p),
Var_page::CHAIN);
}
free_var_part(regFragPtr.p, regTabPtr.p, &tmp, (Var_page*)pagePtr.p, 0);
} else { } else {
free_fix_rec(regFragPtr.p, regTabPtr.p, &tmp, (Fix_page*)pagePtr.p); free_fix_rec(regFragPtr.p, regTabPtr.p, &tmp, (Fix_page*)pagePtr.p);
} }
@ -156,15 +149,19 @@ Dbtup::dealloc_tuple(Signal* signal,
Fragrecord* regFragPtr, Fragrecord* regFragPtr,
Tablerec* regTabPtr) Tablerec* regTabPtr)
{ {
ptr->m_header_bits |= Tuple_header::FREE;
if (ptr->m_header_bits & Tuple_header::DISK_PART) if (ptr->m_header_bits & Tuple_header::DISK_PART)
{ {
Local_key disk; Local_key disk;
memcpy(&disk, ptr->get_disk_ref_ptr(regTabPtr), sizeof(disk)); memcpy(&disk, ptr->get_disk_ref_ptr(regTabPtr), sizeof(disk));
Ptr<GlobalPage> disk_page;
m_global_page_pool.getPtr(disk_page,
regOperPtr->m_commit_disk_callback_page);
disk_page_free(signal, regTabPtr, regFragPtr, disk_page_free(signal, regTabPtr, regFragPtr,
&disk, *(PagePtr*)&disk_page, gci); &disk, *(PagePtr*)&m_pgman.m_ptr, gci);
}
if (regTabPtr->m_bits & Tablerec::TR_RowGCI)
{
jam();
* ptr->get_mm_gci(regTabPtr) = gci;
} }
} }
@ -181,7 +178,7 @@ void
Dbtup::commit_operation(Signal* signal, Dbtup::commit_operation(Signal* signal,
Uint32 gci, Uint32 gci,
Tuple_header* tuple_ptr, Tuple_header* tuple_ptr,
Page* page, PagePtr pagePtr,
Operationrec* regOperPtr, Operationrec* regOperPtr,
Fragrecord* regFragPtr, Fragrecord* regFragPtr,
Tablerec* regTabPtr) Tablerec* regTabPtr)
@ -197,75 +194,38 @@ Dbtup::commit_operation(Signal* signal,
Uint32 copy_bits= copy->m_header_bits; Uint32 copy_bits= copy->m_header_bits;
Uint32 fix_size= regTabPtr->m_offsets[MM].m_fix_header_size; Uint32 fixsize= regTabPtr->m_offsets[MM].m_fix_header_size;
Uint32 mm_vars= regTabPtr->m_attributes[MM].m_no_of_varsize; Uint32 mm_vars= regTabPtr->m_attributes[MM].m_no_of_varsize;
if(mm_vars == 0) if(mm_vars == 0)
{ {
memcpy(tuple_ptr, copy, 4*fix_size); memcpy(tuple_ptr, copy, 4*fixsize);
//ndbout_c("commit: memcpy %p %p %d", tuple_ptr, copy, 4*fix_size); disk_ptr= (Tuple_header*)(((Uint32*)copy)+fixsize);
disk_ptr= (Tuple_header*)(((Uint32*)copy)+fix_size);
}
else if(bits & Tuple_header::CHAINED_ROW)
{
Uint32 *ref= tuple_ptr->get_var_part_ptr(regTabPtr);
memcpy(tuple_ptr, copy, 4*(Tuple_header::HeaderSize+fix_size));
Local_key tmp; tmp.assref(*ref);
if(0) printf("%p %d %d (%d bytes) - ref: %x ", tuple_ptr,
regOperPtr->m_tuple_location.m_page_no,
regOperPtr->m_tuple_location.m_page_idx,
4*(Tuple_header::HeaderSize+fix_size),
*ref);
Ptr<Var_page> vpagePtr;
Uint32 *dst= get_ptr(&vpagePtr, *(Var_part_ref*)ref);
Uint32 *src= copy->get_var_part_ptr(regTabPtr);
Uint32 sz= ((mm_vars + 1) << 1) + (((Uint16*)src)[mm_vars]);
ndbassert(4*vpagePtr.p->get_entry_len(tmp.m_page_idx) >= sz);
memcpy(dst, src, sz);
if(0) printf("ptr: %p %d ref: %x - chain commit", dst, sz, *ref);
copy_bits |= Tuple_header::CHAINED_ROW;
if(0)
{
for(Uint32 i = 0; i<((sz+3)>>2); i++)
printf(" %.8x", src[i]);
printf("\n");
}
if(copy_bits & Tuple_header::MM_SHRINK)
{
if(0) printf(" - shrink %d -> %d - ",
vpagePtr.p->get_entry_len(tmp.m_page_idx), (sz + 3) >> 2);
vpagePtr.p->shrink_entry(tmp.m_page_idx, (sz + 3) >> 2);
if(0)ndbout_c("%p->shrink_entry(%d, %d)", vpagePtr.p, tmp.m_page_idx,
(sz + 3) >> 2);
update_free_page_list(regFragPtr, vpagePtr.p);
}
if(0) ndbout_c("");
disk_ptr = (Tuple_header*)
(((Uint32*)copy)+Tuple_header::HeaderSize+fix_size+((sz + 3) >> 2));
} }
else else
{ {
Uint32 *var_part= copy->get_var_part_ptr(regTabPtr); Uint32 *ref= tuple_ptr->get_var_part_ptr(regTabPtr);
Uint32 sz= Tuple_header::HeaderSize + fix_size + memcpy(tuple_ptr, copy, 4*(Tuple_header::HeaderSize+fixsize));
((((mm_vars + 1) << 1) + (((Uint16*)var_part)[mm_vars]) + 3)>> 2);
ndbassert(((Var_page*)page)-> Local_key tmp; tmp.assref(*ref);
get_entry_len(regOperPtr->m_tuple_location.m_page_idx) >= sz);
memcpy(tuple_ptr, copy, 4*sz); PagePtr vpagePtr;
if(0) ndbout_c("%p %d %d (%d bytes)", tuple_ptr, Uint32 *dst= get_ptr(&vpagePtr, *(Var_part_ref*)ref);
regOperPtr->m_tuple_location.m_page_no, Var_page* vpagePtrP = (Var_page*)vpagePtr.p;
regOperPtr->m_tuple_location.m_page_idx, Uint32 *src= copy->get_var_part_ptr(regTabPtr);
4*sz); Uint32 sz= ((mm_vars + 1) << 1) + (((Uint16*)src)[mm_vars]);
ndbassert(4*vpagePtrP->get_entry_len(tmp.m_page_idx) >= sz);
memcpy(dst, src, sz);
copy_bits |= Tuple_header::CHAINED_ROW;
if(copy_bits & Tuple_header::MM_SHRINK) if(copy_bits & Tuple_header::MM_SHRINK)
{ {
((Var_page*)page)->shrink_entry(regOperPtr->m_tuple_location.m_page_idx, vpagePtrP->shrink_entry(tmp.m_page_idx, (sz + 3) >> 2);
sz); update_free_page_list(regFragPtr, vpagePtr);
if(0)ndbout_c("%p->shrink_entry(%d, %d)",
page, regOperPtr->m_tuple_location.m_page_idx, sz);
update_free_page_list(regFragPtr, (Var_page*)page);
} }
disk_ptr = (Tuple_header*)(((Uint32*)copy)+sz);
disk_ptr = (Tuple_header*)
(((Uint32*)copy)+Tuple_header::HeaderSize+fixsize+((sz + 3) >> 2));
} }
if (regTabPtr->m_no_of_disk_attributes && if (regTabPtr->m_no_of_disk_attributes &&
@ -276,13 +236,13 @@ Dbtup::commit_operation(Signal* signal,
Uint32 logfile_group_id= regFragPtr->m_logfile_group_id; Uint32 logfile_group_id= regFragPtr->m_logfile_group_id;
Uint32 lcpScan_ptr_i= regFragPtr->m_lcp_scan_op; Uint32 lcpScan_ptr_i= regFragPtr->m_lcp_scan_op;
PagePtr pagePtr = *(PagePtr*)&m_pgman.m_ptr; PagePtr diskPagePtr = *(PagePtr*)&m_pgman.m_ptr;
ndbassert(pagePtr.p->m_page_no == key.m_page_no); ndbassert(diskPagePtr.p->m_page_no == key.m_page_no);
ndbassert(pagePtr.p->m_file_no == key.m_file_no); ndbassert(diskPagePtr.p->m_file_no == key.m_file_no);
Uint32 sz, *dst; Uint32 sz, *dst;
if(copy_bits & Tuple_header::DISK_ALLOC) if(copy_bits & Tuple_header::DISK_ALLOC)
{ {
disk_page_alloc(signal, regTabPtr, regFragPtr, &key, pagePtr, gci); disk_page_alloc(signal, regTabPtr, regFragPtr, &key, diskPagePtr, gci);
if(lcpScan_ptr_i != RNIL) if(lcpScan_ptr_i != RNIL)
{ {
@ -301,17 +261,18 @@ Dbtup::commit_operation(Signal* signal,
if(regTabPtr->m_attributes[DD].m_no_of_varsize == 0) if(regTabPtr->m_attributes[DD].m_no_of_varsize == 0)
{ {
sz= regTabPtr->m_offsets[DD].m_fix_header_size; sz= regTabPtr->m_offsets[DD].m_fix_header_size;
dst= ((Fix_page*)pagePtr.p)->get_ptr(key.m_page_idx, sz); dst= ((Fix_page*)diskPagePtr.p)->get_ptr(key.m_page_idx, sz);
} }
else else
{ {
dst= ((Var_page*)pagePtr.p)->get_ptr(key.m_page_idx); dst= ((Var_page*)diskPagePtr.p)->get_ptr(key.m_page_idx);
sz= ((Var_page*)pagePtr.p)->get_entry_len(key.m_page_idx); sz= ((Var_page*)diskPagePtr.p)->get_entry_len(key.m_page_idx);
} }
if(! (copy_bits & Tuple_header::DISK_ALLOC)) if(! (copy_bits & Tuple_header::DISK_ALLOC))
{ {
disk_page_undo_update(pagePtr.p, &key, dst, sz, gci, logfile_group_id); disk_page_undo_update(diskPagePtr.p,
&key, dst, sz, gci, logfile_group_id);
} }
memcpy(dst, disk_ptr, 4*sz); memcpy(dst, disk_ptr, 4*sz);
@ -323,7 +284,7 @@ Dbtup::commit_operation(Signal* signal,
Uint32 clear= Uint32 clear=
Tuple_header::ALLOC | Tuple_header::ALLOC | Tuple_header::FREE |
Tuple_header::DISK_ALLOC | Tuple_header::DISK_INLINE | Tuple_header::DISK_ALLOC | Tuple_header::DISK_INLINE |
Tuple_header::MM_SHRINK | Tuple_header::MM_GROWN; Tuple_header::MM_SHRINK | Tuple_header::MM_GROWN;
copy_bits &= ~(Uint32)clear; copy_bits &= ~(Uint32)clear;
@ -331,7 +292,13 @@ Dbtup::commit_operation(Signal* signal,
tuple_ptr->m_header_bits= copy_bits; tuple_ptr->m_header_bits= copy_bits;
tuple_ptr->m_operation_ptr_i= save; tuple_ptr->m_operation_ptr_i= save;
if (regTabPtr->checksumIndicator) { if (regTabPtr->m_bits & Tablerec::TR_RowGCI)
{
jam();
* tuple_ptr->get_mm_gci(regTabPtr) = gci;
}
if (regTabPtr->m_bits & Tablerec::TR_Checksum) {
jam(); jam();
setChecksum(tuple_ptr, regTabPtr); setChecksum(tuple_ptr, regTabPtr);
} }
@ -505,8 +472,13 @@ void Dbtup::execTUP_COMMITREQ(Signal* signal)
req.m_callback.m_callbackFunction = req.m_callback.m_callbackFunction =
safe_cast(&Dbtup::disk_page_commit_callback); safe_cast(&Dbtup::disk_page_commit_callback);
/*
* Consider commit to be correlated. Otherwise pk op + commit makes
* the page hot. XXX move to TUP which knows better.
*/
int flags= regOperPtr.p->op_struct.op_type | int flags= regOperPtr.p->op_struct.op_type |
Page_cache_client::COMMIT_REQ | Page_cache_client::STRICT_ORDER; Page_cache_client::COMMIT_REQ | Page_cache_client::STRICT_ORDER |
Page_cache_client::CORR_REQ;
int res= m_pgman.get_page(signal, req, flags); int res= m_pgman.get_page(signal, req, flags);
switch(res){ switch(res){
case 0: case 0:
@ -548,9 +520,10 @@ void Dbtup::execTUP_COMMITREQ(Signal* signal)
if(!tuple_ptr) if(!tuple_ptr)
{ {
req_struct.m_tuple_ptr= tuple_ptr = (Tuple_header*) tuple_ptr = (Tuple_header*)
get_ptr(&page, &regOperPtr.p->m_tuple_location,regTabPtr.p); get_ptr(&page, &regOperPtr.p->m_tuple_location,regTabPtr.p);
} }
req_struct.m_tuple_ptr = tuple_ptr;
if(get_tuple_state(regOperPtr.p) == TUPLE_PREPARED) if(get_tuple_state(regOperPtr.p) == TUPLE_PREPARED)
{ {
@ -587,7 +560,7 @@ void Dbtup::execTUP_COMMITREQ(Signal* signal)
if(regOperPtr.p->op_struct.op_type != ZDELETE) if(regOperPtr.p->op_struct.op_type != ZDELETE)
{ {
commit_operation(signal, gci, tuple_ptr, page.p, commit_operation(signal, gci, tuple_ptr, page,
regOperPtr.p, regFragPtr.p, regTabPtr.p); regOperPtr.p, regFragPtr.p, regTabPtr.p);
removeActiveOpList(regOperPtr.p, tuple_ptr); removeActiveOpList(regOperPtr.p, tuple_ptr);
} }

View File

@ -38,7 +38,7 @@ void Dbtup::execDEBUG_SIG(Signal* signal)
PagePtr regPagePtr; PagePtr regPagePtr;
ljamEntry(); ljamEntry();
regPagePtr.i = signal->theData[0]; regPagePtr.i = signal->theData[0];
ptrCheckGuard(regPagePtr, cnoOfPage, cpage); c_page_pool.getPtr(regPagePtr);
}//Dbtup::execDEBUG_SIG() }//Dbtup::execDEBUG_SIG()
#ifdef TEST_MR #ifdef TEST_MR
@ -72,7 +72,7 @@ Dbtup::reportMemoryUsage(Signal* signal, int incDec){
signal->theData[1] = incDec; signal->theData[1] = incDec;
signal->theData[2] = sizeof(Page); signal->theData[2] = sizeof(Page);
signal->theData[3] = cnoOfAllocatedPages; signal->theData[3] = cnoOfAllocatedPages;
signal->theData[4] = cnoOfPage; signal->theData[4] = c_page_pool.getSize();
signal->theData[5] = DBTUP; signal->theData[5] = DBTUP;
sendSignal(CMVMI_REF, GSN_EVENT_REP, signal, 6, JBB); sendSignal(CMVMI_REF, GSN_EVENT_REP, signal, 6, JBB);
} }
@ -168,7 +168,7 @@ Dbtup::execDUMP_STATE_ORD(Signal* signal)
// Case // Case
Uint32 c = (rand() % 3); Uint32 c = (rand() % 3);
const Uint32 free = cnoOfPage - cnoOfAllocatedPages; const Uint32 free = c_page_pool.getSize() - cnoOfAllocatedPages;
Uint32 alloc = 0; Uint32 alloc = 0;
if(free <= 1){ if(free <= 1){
@ -213,7 +213,7 @@ Dbtup::execDUMP_STATE_ORD(Signal* signal)
for(Uint32 i = 0; i<chunk.pageCount; i++){ for(Uint32 i = 0; i<chunk.pageCount; i++){
PagePtr pagePtr; PagePtr pagePtr;
pagePtr.i = chunk.pageId + i; pagePtr.i = chunk.pageId + i;
ptrCheckGuard(pagePtr, cnoOfPage, cpage); c_page_pool.getPtr(pagePtr);
pagePtr.p->page_state = ~ZFREE_COMMON; pagePtr.p->page_state = ~ZFREE_COMMON;
} }
@ -281,8 +281,7 @@ void Dbtup::printoutTuplePage(Uint32 fragid, Uint32 pageid, Uint32 printLimit)
FragrecordPtr tmpFragP; FragrecordPtr tmpFragP;
TablerecPtr tmpTableP; TablerecPtr tmpTableP;
tmpPageP.i = pageid; c_page_pool.getPtr(tmpPageP, pageid);
ptrCheckGuard(tmpPageP, cnoOfPage, cpage);
tmpFragP.i = fragid; tmpFragP.i = fragid;
ptrCheckGuard(tmpFragP, cnoOfFragrec, fragrecord); ptrCheckGuard(tmpFragP, cnoOfFragrec, fragrecord);
@ -334,7 +333,7 @@ operator<<(NdbOut& out, const Dbtup::Th& th)
out << "[Th " << hex << &th; out << "[Th " << hex << &th;
out << " [op " << hex << th.data[i++] << "]"; out << " [op " << hex << th.data[i++] << "]";
out << " [version " << hex << (Uint16)th.data[i++] << "]"; out << " [version " << hex << (Uint16)th.data[i++] << "]";
if (tab.checksumIndicator) if (tab.m_bits & Dbtup::Tablerec::TR_Checksum)
out << " [checksum " << hex << th.data[i++] << "]"; out << " [checksum " << hex << th.data[i++] << "]";
out << " [nullbits"; out << " [nullbits";
for (unsigned j = 0; j < tab.m_offsets[Dbtup::MM].m_null_words; j++) for (unsigned j = 0; j < tab.m_offsets[Dbtup::MM].m_null_words; j++)
@ -381,7 +380,7 @@ NdbOut&
operator<<(NdbOut& out, const Dbtup::Tablerec& tab) operator<<(NdbOut& out, const Dbtup::Tablerec& tab)
{ {
out << "[ total_rec_size: " << tab.total_rec_size out << "[ total_rec_size: " << tab.total_rec_size
<< " checksum: " << tab.checksumIndicator << " checksum: " << !!(tab.m_bits & Dbtup::Tablerec::TR_Checksum)
<< " attr: " << tab.m_no_of_attributes << " attr: " << tab.m_no_of_attributes
<< " disk: " << tab.m_no_of_disk_attributes << " disk: " << tab.m_no_of_disk_attributes
<< " mm: " << tab.m_offsets[Dbtup::MM] << " mm: " << tab.m_offsets[Dbtup::MM]

View File

@ -20,7 +20,8 @@
Dbtup::Disk_alloc_info::Disk_alloc_info(const Tablerec* tabPtrP, Dbtup::Disk_alloc_info::Disk_alloc_info(const Tablerec* tabPtrP,
Uint32 extent_size) Uint32 extent_size)
{ {
m_curr_extent_info_ptr_i= RNIL; m_extent_size = extent_size;
m_curr_extent_info_ptr_i = RNIL;
if (tabPtrP->m_no_of_disk_attributes == 0) if (tabPtrP->m_no_of_disk_attributes == 0)
return; return;
@ -278,6 +279,7 @@ Dbtup::disk_page_prealloc(Signal* signal,
int pages= err; int pages= err;
ndbout << "allocated " << pages << " pages: " << ext.p->m_key << endl; ndbout << "allocated " << pages << " pages: " << ext.p->m_key << endl;
ext.p->m_first_page_no = ext.p->m_key.m_page_no;
bzero(ext.p->m_free_page_count, sizeof(ext.p->m_free_page_count)); bzero(ext.p->m_free_page_count, sizeof(ext.p->m_free_page_count));
ext.p->m_free_space= alloc.m_page_free_bits_map[0] * pages; ext.p->m_free_space= alloc.m_page_free_bits_map[0] * pages;
ext.p->m_free_page_count[0]= pages; // All pages are "free"-est ext.p->m_free_page_count[0]= pages; // All pages are "free"-est
@ -528,8 +530,7 @@ Dbtup::disk_page_prealloc_initial_callback(Signal*signal,
if (tabPtr.p->m_attributes[DD].m_no_of_varsize == 0) if (tabPtr.p->m_attributes[DD].m_no_of_varsize == 0)
{ {
convertThPage(tabPtr.p->m_offsets[DD].m_fix_header_size, convertThPage((Fix_page*)gpage.p, tabPtr.p, DD);
(Fix_page*)gpage.p);
} }
else else
{ {
@ -1060,6 +1061,7 @@ Dbtup::disk_restart_alloc_extent(Uint32 tableId, Uint32 fragId,
ext.p->m_key = *key; ext.p->m_key = *key;
ndbout << "allocated " << pages << " pages: " << ext.p->m_key << endl; ndbout << "allocated " << pages << " pages: " << ext.p->m_key << endl;
ext.p->m_first_page_no = ext.p->m_key.m_page_no;
bzero(ext.p->m_free_page_count, sizeof(ext.p->m_free_page_count)); bzero(ext.p->m_free_page_count, sizeof(ext.p->m_free_page_count));
ext.p->m_free_space= alloc.m_page_free_bits_map[0] * pages; ext.p->m_free_space= alloc.m_page_free_bits_map[0] * pages;
ext.p->m_free_page_count[0]= pages; // All pages are "free"-est ext.p->m_free_page_count[0]= pages; // All pages are "free"-est

File diff suppressed because it is too large Load Diff

View File

@ -73,7 +73,7 @@ Dbtup::alloc_fix_rec(Fragrecord* const regFragPtr,
/* FAILED. TRY ALLOCATING FROM NORMAL PAGE. */ /* FAILED. TRY ALLOCATING FROM NORMAL PAGE. */
/* ---------------------------------------------------------------- */ /* ---------------------------------------------------------------- */
PagePtr pagePtr; PagePtr pagePtr;
pagePtr.i= regFragPtr->thFreeFirst; pagePtr.i = regFragPtr->thFreeFirst.firstItem;
if (pagePtr.i == RNIL) { if (pagePtr.i == RNIL) {
/* ---------------------------------------------------------------- */ /* ---------------------------------------------------------------- */
// No prepared tuple header page with free entries exists. // No prepared tuple header page with free entries exists.
@ -85,14 +85,16 @@ Dbtup::alloc_fix_rec(Fragrecord* const regFragPtr,
// We found empty pages on the fragment. Allocate an empty page and // We found empty pages on the fragment. Allocate an empty page and
// convert it into a tuple header page and put it in thFreeFirst-list. // convert it into a tuple header page and put it in thFreeFirst-list.
/* ---------------------------------------------------------------- */ /* ---------------------------------------------------------------- */
ptrCheckGuard(pagePtr, cnoOfPage, cpage); c_page_pool.getPtr(pagePtr);
convertThPage(regTabPtr->m_offsets[MM].m_fix_header_size, ndbassert(pagePtr.p->page_state == ZEMPTY_MM);
(Fix_page*)pagePtr.p);
convertThPage((Fix_page*)pagePtr.p, regTabPtr, MM);
pagePtr.p->next_page = regFragPtr->thFreeFirst;
pagePtr.p->page_state = ZTH_MM_FREE; pagePtr.p->page_state = ZTH_MM_FREE;
regFragPtr->thFreeFirst = pagePtr.i;
LocalDLList<Page> free_pages(c_page_pool, regFragPtr->thFreeFirst);
free_pages.add(pagePtr);
} else { } else {
ljam(); ljam();
/* ---------------------------------------------------------------- */ /* ---------------------------------------------------------------- */
@ -106,7 +108,7 @@ Dbtup::alloc_fix_rec(Fragrecord* const regFragPtr,
/* THIS SHOULD BE THE COMMON PATH THROUGH THE CODE, FREE */ /* THIS SHOULD BE THE COMMON PATH THROUGH THE CODE, FREE */
/* COPY PAGE EXISTED. */ /* COPY PAGE EXISTED. */
/* ---------------------------------------------------------------- */ /* ---------------------------------------------------------------- */
ptrCheckGuard(pagePtr, cnoOfPage, cpage); c_page_pool.getPtr(pagePtr);
} }
Uint32 page_offset= alloc_tuple_from_page(regFragPtr, (Fix_page*)pagePtr.p); Uint32 page_offset= alloc_tuple_from_page(regFragPtr, (Fix_page*)pagePtr.p);
@ -117,10 +119,11 @@ Dbtup::alloc_fix_rec(Fragrecord* const regFragPtr,
return pagePtr.p->m_data + page_offset; return pagePtr.p->m_data + page_offset;
} }
void Dbtup::convertThPage(Uint32 Tupheadsize, void Dbtup::convertThPage(Fix_page* regPagePtr,
Fix_page* const regPagePtr) Tablerec* regTabPtr,
Uint32 mm)
{ {
Uint32 nextTuple = Tupheadsize; Uint32 nextTuple = regTabPtr->m_offsets[mm].m_fix_header_size;
Uint32 endOfList; Uint32 endOfList;
/* /*
ASSUMES AT LEAST ONE TUPLE HEADER FITS AND THEREFORE NO HANDLING ASSUMES AT LEAST ONE TUPLE HEADER FITS AND THEREFORE NO HANDLING
@ -132,10 +135,19 @@ void Dbtup::convertThPage(Uint32 Tupheadsize,
#ifdef VM_TRACE #ifdef VM_TRACE
memset(regPagePtr->m_data, 0xF1, 4*Fix_page::DATA_WORDS); memset(regPagePtr->m_data, 0xF1, 4*Fix_page::DATA_WORDS);
#endif #endif
Uint32 gci_pos = 2;
Uint32 gci_val = 0xF1F1F1F1;
if (regTabPtr->m_bits & Tablerec::TR_RowGCI)
{
Tuple_header* ptr = 0;
gci_pos = ptr->get_mm_gci(regTabPtr) - (Uint32*)ptr;
gci_val = 0;
}
while (pos + nextTuple <= Fix_page::DATA_WORDS) while (pos + nextTuple <= Fix_page::DATA_WORDS)
{ {
regPagePtr->m_data[pos] = (prev << 16) | (pos + nextTuple); regPagePtr->m_data[pos] = (prev << 16) | (pos + nextTuple);
regPagePtr->m_data[pos + 1] = Tuple_header::FREE; regPagePtr->m_data[pos + 1] = Fix_page::FREE_RECORD;
regPagePtr->m_data[pos + gci_pos] = gci_val;
prev = pos; prev = pos;
pos += nextTuple; pos += nextTuple;
cnt ++; cnt ++;
@ -151,6 +163,7 @@ Uint32
Dbtup::alloc_tuple_from_page(Fragrecord* const regFragPtr, Dbtup::alloc_tuple_from_page(Fragrecord* const regFragPtr,
Fix_page* const regPagePtr) Fix_page* const regPagePtr)
{ {
ndbassert(regPagePtr->free_space);
Uint32 idx= regPagePtr->alloc_record(); Uint32 idx= regPagePtr->alloc_record();
if(regPagePtr->free_space == 0) if(regPagePtr->free_space == 0)
{ {
@ -164,8 +177,8 @@ Dbtup::alloc_tuple_from_page(Fragrecord* const regFragPtr,
/* ARE MAINTAINED EVEN AFTER A SYSTEM CRASH. */ /* ARE MAINTAINED EVEN AFTER A SYSTEM CRASH. */
/* ---------------------------------------------------------------- */ /* ---------------------------------------------------------------- */
ndbrequire(regPagePtr->page_state == ZTH_MM_FREE); ndbrequire(regPagePtr->page_state == ZTH_MM_FREE);
regFragPtr->thFreeFirst = regPagePtr->next_page; LocalDLList<Page> free_pages(c_page_pool, regFragPtr->thFreeFirst);
regPagePtr->next_page = RNIL; free_pages.remove((Page*)regPagePtr);
regPagePtr->page_state = ZTH_MM_FULL; regPagePtr->page_state = ZTH_MM_FULL;
} }
@ -183,10 +196,92 @@ void Dbtup::free_fix_rec(Fragrecord* regFragPtr,
if(free == 1) if(free == 1)
{ {
ljam(); ljam();
PagePtr pagePtr = { (Page*)regPagePtr, key->m_page_no };
LocalDLList<Page> free_pages(c_page_pool, regFragPtr->thFreeFirst);
ndbrequire(regPagePtr->page_state == ZTH_MM_FULL); ndbrequire(regPagePtr->page_state == ZTH_MM_FULL);
regPagePtr->page_state = ZTH_MM_FREE; regPagePtr->page_state = ZTH_MM_FREE;
regPagePtr->next_page= regFragPtr->thFreeFirst; free_pages.add(pagePtr);
regFragPtr->thFreeFirst = key->m_page_no;
} }
}//Dbtup::freeTh() }//Dbtup::freeTh()
int
Dbtup::alloc_page(Tablerec* tabPtrP, Fragrecord* fragPtrP,
PagePtr * ret, Uint32 page_no)
{
Uint32 pages = fragPtrP->noOfPages;
if (page_no >= pages)
{
Uint32 start = pages;
while(page_no >= pages)
pages += (pages >> 3) + (pages >> 4) + 2;
allocFragPages(fragPtrP, pages - start);
if (page_no >= (pages = fragPtrP->noOfPages))
{
terrorCode = ZMEM_NOMEM_ERROR;
return 1;
}
}
PagePtr pagePtr;
c_page_pool.getPtr(pagePtr, getRealpid(fragPtrP, page_no));
LocalDLList<Page> alloc_pages(c_page_pool, fragPtrP->emptyPrimPage);
LocalDLList<Page> free_pages(c_page_pool, fragPtrP->thFreeFirst);
if (pagePtr.p->page_state == ZEMPTY_MM)
{
convertThPage((Fix_page*)pagePtr.p, tabPtrP, MM);
pagePtr.p->page_state = ZTH_MM_FREE;
alloc_pages.remove(pagePtr);
free_pages.add(pagePtr);
}
*ret = pagePtr;
return 0;
}
Uint32*
Dbtup::alloc_fix_rowid(Fragrecord* const regFragPtr,
Tablerec* const regTabPtr,
Local_key* key,
Uint32 * out_frag_page_id)
{
Uint32 page_no = key->m_page_no;
Uint32 idx= key->m_page_idx;
PagePtr pagePtr;
if (alloc_page(regTabPtr, regFragPtr, &pagePtr, page_no))
{
terrorCode = ZMEM_NOMEM_ERROR;
return 0;
}
Uint32 state = pagePtr.p->page_state;
LocalDLList<Page> free_pages(c_page_pool, regFragPtr->thFreeFirst);
switch(state){
case ZTH_MM_FREE:
if (((Fix_page*)pagePtr.p)->alloc_record(idx) != idx)
{
terrorCode = ZROWID_ALLOCATED;
return 0;
}
if(pagePtr.p->free_space == 0)
{
jam();
pagePtr.p->page_state = ZTH_MM_FULL;
free_pages.remove(pagePtr);
}
*out_frag_page_id= page_no;
key->m_page_no = pagePtr.i;
key->m_page_idx = idx;
return pagePtr.p->m_data + idx;
case ZTH_MM_FULL:
terrorCode = ZROWID_ALLOCATED;
return 0;
case ZEMPTY_MM:
ndbrequire(false);
}
}

View File

@ -42,7 +42,6 @@ void Dbtup::initData()
{ {
cnoOfAttrbufrec = ZNO_OF_ATTRBUFREC; cnoOfAttrbufrec = ZNO_OF_ATTRBUFREC;
cnoOfFragrec = MAX_FRAG_PER_NODE; cnoOfFragrec = MAX_FRAG_PER_NODE;
cnoOfPage = ZNO_OF_PAGE;
cnoOfFragoprec = MAX_FRAG_PER_NODE; cnoOfFragoprec = MAX_FRAG_PER_NODE;
cnoOfPageRangeRec = ZNO_OF_PAGE_RANGE_REC; cnoOfPageRangeRec = ZNO_OF_PAGE_RANGE_REC;
c_maxTriggersPerTable = ZDEFAULT_MAX_NO_TRIGGERS_PER_TABLE; c_maxTriggersPerTable = ZDEFAULT_MAX_NO_TRIGGERS_PER_TABLE;
@ -55,11 +54,11 @@ void Dbtup::initData()
Dbtup::Dbtup(const class Configuration & conf, Pgman* pgman) Dbtup::Dbtup(const class Configuration & conf, Pgman* pgman)
: SimulatedBlock(DBTUP, conf), : SimulatedBlock(DBTUP, conf),
c_lqh(0), c_lqh(0),
m_pgman(this, pgman),
c_extent_hash(c_extent_pool),
c_storedProcPool(), c_storedProcPool(),
c_buildIndexList(c_buildIndexPool), c_buildIndexList(c_buildIndexPool),
c_undo_buffer(this), c_undo_buffer(this)
m_pgman(this, pgman),
c_extent_hash(c_extent_pool)
{ {
BLOCK_CONSTRUCTOR(Dbtup); BLOCK_CONSTRUCTOR(Dbtup);
@ -101,12 +100,14 @@ Dbtup::Dbtup(const class Configuration & conf, Pgman* pgman)
addRecSignal(GSN_ACC_SCANREQ, &Dbtup::execACC_SCANREQ); addRecSignal(GSN_ACC_SCANREQ, &Dbtup::execACC_SCANREQ);
addRecSignal(GSN_NEXT_SCANREQ, &Dbtup::execNEXT_SCANREQ); addRecSignal(GSN_NEXT_SCANREQ, &Dbtup::execNEXT_SCANREQ);
addRecSignal(GSN_ACC_CHECK_SCAN, &Dbtup::execACC_CHECK_SCAN); addRecSignal(GSN_ACC_CHECK_SCAN, &Dbtup::execACC_CHECK_SCAN);
addRecSignal(GSN_ACCKEYCONF, &Dbtup::execACCKEYCONF);
addRecSignal(GSN_ACCKEYREF, &Dbtup::execACCKEYREF);
addRecSignal(GSN_ACC_ABORTCONF, &Dbtup::execACC_ABORTCONF);
attrbufrec = 0; attrbufrec = 0;
fragoperrec = 0; fragoperrec = 0;
fragrecord = 0; fragrecord = 0;
hostBuffer = 0; hostBuffer = 0;
cpage = 0;
pageRange = 0; pageRange = 0;
tablerec = 0; tablerec = 0;
tableDescriptor = 0; tableDescriptor = 0;
@ -135,10 +136,6 @@ Dbtup::~Dbtup()
sizeof(HostBuffer), sizeof(HostBuffer),
MAX_NODES); MAX_NODES);
deallocRecord((void **)&cpage,"Page",
sizeof(Page),
cnoOfPage);
deallocRecord((void **)&pageRange,"PageRange", deallocRecord((void **)&pageRange,"PageRange",
sizeof(PageRange), sizeof(PageRange),
cnoOfPageRangeRec); cnoOfPageRangeRec);
@ -173,7 +170,7 @@ void Dbtup::execCONTINUEB(Signal* signal)
case ZREPORT_MEMORY_USAGE:{ case ZREPORT_MEMORY_USAGE:{
ljam(); ljam();
static int c_currentMemUsed = 0; static int c_currentMemUsed = 0;
int now = (cnoOfAllocatedPages * 100)/cnoOfPage; int now = (cnoOfAllocatedPages * 100)/c_page_pool.getSize();
const int thresholds[] = { 100, 90, 80, 0 }; const int thresholds[] = { 100, 90, 80, 0 };
Uint32 i = 0; Uint32 i = 0;
@ -197,6 +194,14 @@ void Dbtup::execCONTINUEB(Signal* signal)
ljam(); ljam();
buildIndex(signal, dataPtr); buildIndex(signal, dataPtr);
break; break;
case ZTUP_SCAN:
ljam();
{
ScanOpPtr scanPtr;
c_scanOpPool.getPtr(scanPtr, dataPtr);
scanCont(signal, scanPtr);
}
return;
case ZFREE_EXTENT: case ZFREE_EXTENT:
{ {
ljam(); ljam();
@ -279,7 +284,6 @@ void Dbtup::execREAD_CONFIG_REQ(Signal* signal)
ndbrequire(p != 0); ndbrequire(p != 0);
ndbrequire(!ndb_mgm_get_int_parameter(p, CFG_TUP_FRAG, &cnoOfFragrec)); ndbrequire(!ndb_mgm_get_int_parameter(p, CFG_TUP_FRAG, &cnoOfFragrec));
ndbrequire(!ndb_mgm_get_int_parameter(p, CFG_TUP_PAGE, &cnoOfPage));
Uint32 noOfTriggers= 0; Uint32 noOfTriggers= 0;
@ -310,6 +314,9 @@ void Dbtup::execREAD_CONFIG_REQ(Signal* signal)
Uint32 nScanOp; // use TUX config for now Uint32 nScanOp; // use TUX config for now
ndbrequire(!ndb_mgm_get_int_parameter(p, CFG_TUX_SCAN_OP, &nScanOp)); ndbrequire(!ndb_mgm_get_int_parameter(p, CFG_TUX_SCAN_OP, &nScanOp));
c_scanOpPool.setSize(nScanOp + 1); c_scanOpPool.setSize(nScanOp + 1);
Uint32 nScanBatch;
ndbrequire(!ndb_mgm_get_int_parameter(p, CFG_DB_BATCH_SIZE, &nScanBatch));
c_scanLockPool.setSize(nScanOp * nScanBatch);
ScanOpPtr lcp; ScanOpPtr lcp;
ndbrequire(c_scanOpPool.seize(lcp)); ndbrequire(c_scanOpPool.seize(lcp));
@ -326,12 +333,16 @@ void Dbtup::execREAD_CONFIG_REQ(Signal* signal)
void Dbtup::initRecords() void Dbtup::initRecords()
{ {
unsigned i; unsigned i;
Uint32 tmp;
const ndb_mgm_configuration_iterator * p =
theConfiguration.getOwnConfigIterator();
ndbrequire(p != 0);
ndbrequire(!ndb_mgm_get_int_parameter(p, CFG_TUP_PAGE, &tmp));
// Records with dynamic sizes // Records with dynamic sizes
cpage = (Page*)allocRecord("Page", Page* ptr =(Page*)allocRecord("Page", sizeof(Page), tmp, false);
sizeof(Page), c_page_pool.set(ptr, tmp);
cnoOfPage,
false);
attrbufrec = (Attrbufrec*)allocRecord("Attrbufrec", attrbufrec = (Attrbufrec*)allocRecord("Attrbufrec",
sizeof(Attrbufrec), sizeof(Attrbufrec),
@ -353,10 +364,6 @@ void Dbtup::initRecords()
sizeof(TableDescriptor), sizeof(TableDescriptor),
cnoOfTabDescrRec); cnoOfTabDescrRec);
Uint32 tmp;
const ndb_mgm_configuration_iterator * p =
theConfiguration.getOwnConfigIterator();
ndbrequire(p != 0);
ndbrequire(!ndb_mgm_get_int_parameter(p, CFG_TUP_OP_RECS, &tmp)); ndbrequire(!ndb_mgm_get_int_parameter(p, CFG_TUP_OP_RECS, &tmp));
c_operation_pool.setSize(tmp); c_operation_pool.setSize(tmp);
@ -531,6 +538,7 @@ void Dbtup::initializeFragrecord()
for (regFragPtr.i = 0; regFragPtr.i < cnoOfFragrec; regFragPtr.i++) { for (regFragPtr.i = 0; regFragPtr.i < cnoOfFragrec; regFragPtr.i++) {
refresh_watch_dog(); refresh_watch_dog();
ptrAss(regFragPtr, fragrecord); ptrAss(regFragPtr, fragrecord);
new (regFragPtr.p) Fragrecord();
regFragPtr.p->nextfreefrag = regFragPtr.i + 1; regFragPtr.p->nextfreefrag = regFragPtr.i + 1;
regFragPtr.p->fragStatus = IDLE; regFragPtr.p->fragStatus = IDLE;
}//for }//for
@ -582,7 +590,7 @@ Dbtup::initTab(Tablerec* const regTabPtr)
regTabPtr->tabDescriptor = RNIL; regTabPtr->tabDescriptor = RNIL;
regTabPtr->readKeyArray = RNIL; regTabPtr->readKeyArray = RNIL;
regTabPtr->checksumIndicator = false; regTabPtr->m_bits = 0;
regTabPtr->m_no_of_attributes = 0; regTabPtr->m_no_of_attributes = 0;
regTabPtr->noOfKeyAttr = 0; regTabPtr->noOfKeyAttr = 0;

View File

@ -37,8 +37,7 @@ Dbtup::tuxGetTupAddr(Uint32 fragPtrI,
{ {
ljamEntry(); ljamEntry();
PagePtr pagePtr; PagePtr pagePtr;
pagePtr.i= pageId; c_page_pool.getPtr(pagePtr, pageId);
ptrCheckGuard(pagePtr, cnoOfPage, cpage);
Uint32 fragPageId= pagePtr.p->frag_page_id; Uint32 fragPageId= pagePtr.p->frag_page_id;
tupAddr= (fragPageId << MAX_TUPLES_BITS) | pageIndex; tupAddr= (fragPageId << MAX_TUPLES_BITS) | pageIndex;
} }
@ -115,8 +114,7 @@ Dbtup::tuxGetNode(Uint32 fragPtrI,
tablePtr.i= fragPtr.p->fragTableId; tablePtr.i= fragPtr.p->fragTableId;
ptrCheckGuard(tablePtr, cnoOfTablerec, tablerec); ptrCheckGuard(tablePtr, cnoOfTablerec, tablerec);
PagePtr pagePtr; PagePtr pagePtr;
pagePtr.i= pageId; c_page_pool.getPtr(pagePtr, pageId);
ptrCheckGuard(pagePtr, cnoOfPage, cpage);
Uint32 attrDescIndex= tablePtr.p->tabDescriptor + (0 << ZAD_LOG_SIZE); Uint32 attrDescIndex= tablePtr.p->tabDescriptor + (0 << ZAD_LOG_SIZE);
Uint32 attrDataOffset= AttributeOffset::getOffset( Uint32 attrDataOffset= AttributeOffset::getOffset(
tableDescriptor[attrDescIndex + 1].tabDescr); tableDescriptor[attrDescIndex + 1].tabDescr);
@ -219,7 +217,24 @@ Dbtup::tuxReadPk(Uint32 fragPtrI, Uint32 pageId, Uint32 pageIndex, Uint32* dataO
tmpOp.m_tuple_location.m_page_idx= pageIndex; tmpOp.m_tuple_location.m_page_idx= pageIndex;
KeyReqStruct req_struct; KeyReqStruct req_struct;
setup_fixed_part(&req_struct, &tmpOp, tablePtr.p);
PagePtr page_ptr;
Uint32* ptr= get_ptr(&page_ptr, &tmpOp.m_tuple_location, tablePtr.p);
req_struct.m_page_ptr = page_ptr;
req_struct.m_tuple_ptr = (Tuple_header*)ptr;
int ret = 0;
if (! (req_struct.m_tuple_ptr->m_header_bits & Tuple_header::FREE))
{
req_struct.check_offset[MM]= tablePtr.p->get_check_offset(MM);
req_struct.check_offset[DD]= tablePtr.p->get_check_offset(DD);
Uint32 num_attr= tablePtr.p->m_no_of_attributes;
Uint32 descr_start= tablePtr.p->tabDescriptor;
TableDescriptor *tab_descr= &tableDescriptor[descr_start];
ndbrequire(descr_start + (num_attr << ZAD_LOG_SIZE) <= cnoOfTabDescrRec);
req_struct.attr_descr= tab_descr;
if(req_struct.m_tuple_ptr->m_header_bits & Tuple_header::ALLOC) if(req_struct.m_tuple_ptr->m_header_bits & Tuple_header::ALLOC)
{ {
Uint32 opPtrI= req_struct.m_tuple_ptr->m_operation_ptr_i; Uint32 opPtrI= req_struct.m_tuple_ptr->m_operation_ptr_i;
@ -246,7 +261,7 @@ Dbtup::tuxReadPk(Uint32 fragPtrI, Uint32 pageId, Uint32 pageIndex, Uint32* dataO
operPtr.p= NULL; operPtr.p= NULL;
// do it // do it
int ret = readAttributes(&req_struct, ret = readAttributes(&req_struct,
attrIds, attrIds,
numAttrs, numAttrs,
dataOut, dataOut,
@ -276,6 +291,15 @@ Dbtup::tuxReadPk(Uint32 fragPtrI, Uint32 pageId, Uint32 pageIndex, Uint32* dataO
} else { } else {
ret= terrorCode ? (-(int)terrorCode) : -1; ret= terrorCode ? (-(int)terrorCode) : -1;
} }
}
if (tablePtr.p->m_bits & Tablerec::TR_RowGCI)
{
dataOut[ret] = *req_struct.m_tuple_ptr->get_mm_gci(tablePtr.p);
}
else
{
dataOut[ret] = 0;
}
return ret; return ret;
} }
@ -454,7 +478,9 @@ Dbtup::buildIndex(Signal* signal, Uint32 buildPtrI)
tablePtr.i= buildReq->getTableId(); tablePtr.i= buildReq->getTableId();
ptrCheckGuard(tablePtr, cnoOfTablerec, tablerec); ptrCheckGuard(tablePtr, cnoOfTablerec, tablerec);
const Uint32 firstTupleNo = ! buildPtr.p->m_build_vs ? 0 : 1; const Uint32 firstTupleNo = 0;
const Uint32 tupheadsize = tablePtr.p->m_offsets[MM].m_fix_header_size +
(buildPtr.p->m_build_vs ? Tuple_header::HeaderSize + 1: 0);
#ifdef TIME_MEASUREMENT #ifdef TIME_MEASUREMENT
MicroSecondTimer start; MicroSecondTimer start;
@ -491,8 +517,7 @@ Dbtup::buildIndex(Signal* signal, Uint32 buildPtrI)
break; break;
} }
Uint32 realPageId= getRealpid(fragPtr.p, buildPtr.p->m_pageId); Uint32 realPageId= getRealpid(fragPtr.p, buildPtr.p->m_pageId);
pagePtr.i= realPageId; c_page_pool.getPtr(pagePtr, realPageId);
ptrCheckGuard(pagePtr, cnoOfPage, cpage);
Uint32 pageState= pagePtr.p->page_state; Uint32 pageState= pagePtr.p->page_state;
// skip empty page // skip empty page
if (pageState == ZEMPTY_MM) { if (pageState == ZEMPTY_MM) {
@ -504,8 +529,6 @@ Dbtup::buildIndex(Signal* signal, Uint32 buildPtrI)
// get tuple // get tuple
Uint32 pageIndex = ~0; Uint32 pageIndex = ~0;
const Tuple_header* tuple_ptr = 0; const Tuple_header* tuple_ptr = 0;
if (! buildPtr.p->m_build_vs) {
Uint32 tupheadsize= tablePtr.p->m_offsets[MM].m_fix_header_size;
pageIndex = buildPtr.p->m_tupleNo * tupheadsize; pageIndex = buildPtr.p->m_tupleNo * tupheadsize;
if (pageIndex + tupheadsize > Fix_page::DATA_WORDS) { if (pageIndex + tupheadsize > Fix_page::DATA_WORDS) {
ljam(); ljam();
@ -520,28 +543,6 @@ Dbtup::buildIndex(Signal* signal, Uint32 buildPtrI)
buildPtr.p->m_tupleNo++; buildPtr.p->m_tupleNo++;
break; break;
} }
} else {
pageIndex = buildPtr.p->m_tupleNo;
Var_page* page_ptr = (Var_page*)pagePtr.p;
if (pageIndex >= page_ptr->high_index) {
ljam();
buildPtr.p->m_pageId++;
buildPtr.p->m_tupleNo= firstTupleNo;
break;
}
Uint32 len= page_ptr->get_entry_len(pageIndex);
if (len == 0) {
ljam();
buildPtr.p->m_tupleNo++;
break;
}
if (len & Var_page::CHAIN) {
ljam();
buildPtr.p->m_tupleNo++;
break;
}
tuple_ptr = (Tuple_header*)page_ptr->get_ptr(pageIndex);
}
Uint32 tupVersion= tuple_ptr->get_tuple_version(); Uint32 tupVersion= tuple_ptr->get_tuple_version();
OperationrecPtr pageOperPtr; OperationrecPtr pageOperPtr;
pageOperPtr.i= tuple_ptr->m_operation_ptr_i; pageOperPtr.i= tuple_ptr->m_operation_ptr_i;

View File

@ -61,6 +61,7 @@ void Dbtup::execTUPFRAGREQ(Signal* signal)
//Uint32 noOfNewAttr= (signal->theData[10] & 0xFFFF); //Uint32 noOfNewAttr= (signal->theData[10] & 0xFFFF);
/* DICT sends number of character sets in upper half */ /* DICT sends number of character sets in upper half */
Uint32 noOfCharsets= (signal->theData[10] >> 16); Uint32 noOfCharsets= (signal->theData[10] >> 16);
Uint32 gcpIndicator = signal->theData[13];
Uint32 tablespace= signal->theData[14]; Uint32 tablespace= signal->theData[14];
Uint32 checksumIndicator= signal->theData[11]; Uint32 checksumIndicator= signal->theData[11];
@ -133,12 +134,6 @@ void Dbtup::execTUPFRAGREQ(Signal* signal)
return; return;
} }
regFragPtr.p->emptyPrimPage= RNIL;
regFragPtr.p->thFreeFirst= RNIL;
regFragPtr.p->free_var_page_array[0]= RNIL;
regFragPtr.p->free_var_page_array[1]= RNIL;
regFragPtr.p->free_var_page_array[2]= RNIL;
regFragPtr.p->free_var_page_array[3]= RNIL;
regFragPtr.p->fragTableId= regTabPtr.i; regFragPtr.p->fragTableId= regTabPtr.i;
regFragPtr.p->fragmentId= fragId; regFragPtr.p->fragmentId= fragId;
regFragPtr.p->m_tablespace_id= tablespace; regFragPtr.p->m_tablespace_id= tablespace;
@ -181,7 +176,9 @@ void Dbtup::execTUPFRAGREQ(Signal* signal)
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
fragOperPtr.p->definingFragment= true; fragOperPtr.p->definingFragment= true;
regTabPtr.p->tableStatus= DEFINING; regTabPtr.p->tableStatus= DEFINING;
regTabPtr.p->checksumIndicator= (checksumIndicator != 0 ? true : false); regTabPtr.p->m_bits = 0;
regTabPtr.p->m_bits |= (checksumIndicator ? Tablerec::TR_Checksum : 0);
regTabPtr.p->m_bits |= (gcpIndicator ? Tablerec::TR_RowGCI : 0);
regTabPtr.p->m_offsets[MM].m_disk_ref_offset= 0; regTabPtr.p->m_offsets[MM].m_disk_ref_offset= 0;
regTabPtr.p->m_offsets[MM].m_null_words= 0; regTabPtr.p->m_offsets[MM].m_null_words= 0;
@ -443,11 +440,17 @@ void Dbtup::execTUP_ADD_ATTRREQ(Signal* signal)
* Fix offsets * Fix offsets
*/ */
Uint32 pos[2] = { 0, 0 }; Uint32 pos[2] = { 0, 0 };
if(regTabPtr.p->checksumIndicator) if (regTabPtr.p->m_bits & Tablerec::TR_Checksum)
{ {
pos[0]= 1; pos[0]= 1;
} }
if (regTabPtr.p->m_bits & Tablerec::TR_RowGCI)
{
pos[MM]++;
pos[DD]++;
}
regTabPtr.p->m_no_of_disk_attributes= regTabPtr.p->m_no_of_disk_attributes=
regTabPtr.p->m_attributes[DD].m_no_of_fixsize + regTabPtr.p->m_attributes[DD].m_no_of_fixsize +
regTabPtr.p->m_attributes[DD].m_no_of_varsize; regTabPtr.p->m_attributes[DD].m_no_of_varsize;

View File

@ -121,10 +121,10 @@ void Dbtup::initializePage()
cfreepageList[i] = RNIL; cfreepageList[i] = RNIL;
}//for }//for
PagePtr pagePtr; PagePtr pagePtr;
for (pagePtr.i = 0; pagePtr.i < cnoOfPage; pagePtr.i++) { for (pagePtr.i = 0; pagePtr.i < c_page_pool.getSize(); pagePtr.i++) {
ljam(); ljam();
refresh_watch_dog(); refresh_watch_dog();
ptrAss(pagePtr, cpage); c_page_pool.getPtr(pagePtr);
pagePtr.p->physical_page_id= RNIL; pagePtr.p->physical_page_id= RNIL;
pagePtr.p->next_page = pagePtr.i + 1; pagePtr.p->next_page = pagePtr.i + 1;
pagePtr.p->first_cluster_page = RNIL; pagePtr.p->first_cluster_page = RNIL;
@ -133,24 +133,20 @@ void Dbtup::initializePage()
pagePtr.p->prev_page = RNIL; pagePtr.p->prev_page = RNIL;
pagePtr.p->page_state = ZFREE_COMMON; pagePtr.p->page_state = ZFREE_COMMON;
}//for }//for
pagePtr.i = cnoOfPage - 1;
ptrAss(pagePtr, cpage);
pagePtr.p->next_page = RNIL; pagePtr.p->next_page = RNIL;
/**
* Page 0 cant be part of buddy as
* it will scan left right when searching for bigger blocks,
* if 0 is part of arrat, it can search to -1...which is not good
*/
pagePtr.i = 0; pagePtr.i = 0;
ptrAss(pagePtr, cpage); c_page_pool.getPtr(pagePtr);
pagePtr.p->page_state = ~ZFREE_COMMON; pagePtr.p->page_state = ~ZFREE_COMMON;
for(size_t j = 0; j<MAX_PARALLELL_TUP_SRREQ; j++){ Uint32 tmp = 1;
pagePtr.i = 1+j; returnCommonArea(tmp, c_page_pool.getSize() - tmp);
ptrAss(pagePtr, cpage);
pagePtr.p->page_state = ~ZFREE_COMMON;
}
Uint32 tmp = 1 + MAX_PARALLELL_TUP_SRREQ;
returnCommonArea(tmp, cnoOfPage - tmp);
cnoOfAllocatedPages = tmp; // Is updated by returnCommonArea cnoOfAllocatedPages = tmp; // Is updated by returnCommonArea
c_sr_free_page_0 = ~0;
}//Dbtup::initializePage() }//Dbtup::initializePage()
void Dbtup::allocConsPages(Uint32 noOfPagesToAllocate, void Dbtup::allocConsPages(Uint32 noOfPagesToAllocate,
@ -234,7 +230,7 @@ void Dbtup::findFreeLeftNeighbours(Uint32& allocPageRef,
while (allocPageRef > 0) { while (allocPageRef > 0) {
ljam(); ljam();
pageLastPtr.i = allocPageRef - 1; pageLastPtr.i = allocPageRef - 1;
ptrCheckGuard(pageLastPtr, cnoOfPage, cpage); c_page_pool.getPtr(pageLastPtr);
if (pageLastPtr.p->page_state != ZFREE_COMMON) { if (pageLastPtr.p->page_state != ZFREE_COMMON) {
ljam(); ljam();
return; return;
@ -272,10 +268,10 @@ void Dbtup::findFreeRightNeighbours(Uint32& allocPageRef,
ljam(); ljam();
return; return;
}//if }//if
while ((allocPageRef + noPagesAllocated) < cnoOfPage) { while ((allocPageRef + noPagesAllocated) < c_page_pool.getSize()) {
ljam(); ljam();
pageFirstPtr.i = allocPageRef + noPagesAllocated; pageFirstPtr.i = allocPageRef + noPagesAllocated;
ptrCheckGuard(pageFirstPtr, cnoOfPage, cpage); c_page_pool.getPtr(pageFirstPtr);
if (pageFirstPtr.p->page_state != ZFREE_COMMON) { if (pageFirstPtr.p->page_state != ZFREE_COMMON) {
ljam(); ljam();
return; return;
@ -307,8 +303,7 @@ void Dbtup::insertCommonArea(Uint32 insPageRef, Uint32 insList)
cnoOfAllocatedPages -= (1 << insList); cnoOfAllocatedPages -= (1 << insList);
PagePtr pageLastPtr, pageInsPtr; PagePtr pageLastPtr, pageInsPtr;
pageInsPtr.i = insPageRef; c_page_pool.getPtr(pageInsPtr, insPageRef);
ptrCheckGuard(pageInsPtr, cnoOfPage, cpage);
ndbrequire(insList < 16); ndbrequire(insList < 16);
pageLastPtr.i = (pageInsPtr.i + (1 << insList)) - 1; pageLastPtr.i = (pageInsPtr.i + (1 << insList)) - 1;
@ -317,7 +312,7 @@ void Dbtup::insertCommonArea(Uint32 insPageRef, Uint32 insList)
pageInsPtr.p->last_cluster_page = pageLastPtr.i; pageInsPtr.p->last_cluster_page = pageLastPtr.i;
cfreepageList[insList] = pageInsPtr.i; cfreepageList[insList] = pageInsPtr.i;
ptrCheckGuard(pageLastPtr, cnoOfPage, cpage); c_page_pool.getPtr(pageLastPtr);
pageLastPtr.p->first_cluster_page = pageInsPtr.i; pageLastPtr.p->first_cluster_page = pageInsPtr.i;
pageLastPtr.p->next_page = RNIL; pageLastPtr.p->next_page = RNIL;
}//Dbtup::insertCommonArea() }//Dbtup::insertCommonArea()
@ -327,8 +322,7 @@ void Dbtup::removeCommonArea(Uint32 remPageRef, Uint32 list)
cnoOfAllocatedPages += (1 << list); cnoOfAllocatedPages += (1 << list);
PagePtr pagePrevPtr, pageNextPtr, pageLastPtr, pageSearchPtr, remPagePtr; PagePtr pagePrevPtr, pageNextPtr, pageLastPtr, pageSearchPtr, remPagePtr;
remPagePtr.i = remPageRef; c_page_pool.getPtr(remPagePtr, remPageRef);
ptrCheckGuard(remPagePtr, cnoOfPage, cpage);
ndbrequire(list < 16); ndbrequire(list < 16);
if (cfreepageList[list] == remPagePtr.i) { if (cfreepageList[list] == remPagePtr.i) {
ljam(); ljam();
@ -336,14 +330,14 @@ void Dbtup::removeCommonArea(Uint32 remPageRef, Uint32 list)
pageNextPtr.i = cfreepageList[list]; pageNextPtr.i = cfreepageList[list];
if (pageNextPtr.i != RNIL) { if (pageNextPtr.i != RNIL) {
ljam(); ljam();
ptrCheckGuard(pageNextPtr, cnoOfPage, cpage); c_page_pool.getPtr(pageNextPtr);
pageNextPtr.p->prev_cluster_page = RNIL; pageNextPtr.p->prev_cluster_page = RNIL;
}//if }//if
} else { } else {
pageSearchPtr.i = cfreepageList[list]; pageSearchPtr.i = cfreepageList[list];
while (true) { while (true) {
ljam(); ljam();
ptrCheckGuard(pageSearchPtr, cnoOfPage, cpage); c_page_pool.getPtr(pageSearchPtr);
pagePrevPtr = pageSearchPtr; pagePrevPtr = pageSearchPtr;
pageSearchPtr.i = pageSearchPtr.p->next_cluster_page; pageSearchPtr.i = pageSearchPtr.p->next_cluster_page;
if (pageSearchPtr.i == remPagePtr.i) { if (pageSearchPtr.i == remPagePtr.i) {
@ -355,7 +349,7 @@ void Dbtup::removeCommonArea(Uint32 remPageRef, Uint32 list)
pagePrevPtr.p->next_cluster_page = pageNextPtr.i; pagePrevPtr.p->next_cluster_page = pageNextPtr.i;
if (pageNextPtr.i != RNIL) { if (pageNextPtr.i != RNIL) {
ljam(); ljam();
ptrCheckGuard(pageNextPtr, cnoOfPage, cpage); c_page_pool.getPtr(pageNextPtr);
pageNextPtr.p->prev_cluster_page = pagePrevPtr.i; pageNextPtr.p->prev_cluster_page = pagePrevPtr.i;
}//if }//if
}//if }//if
@ -364,6 +358,6 @@ void Dbtup::removeCommonArea(Uint32 remPageRef, Uint32 list)
remPagePtr.p->prev_cluster_page= RNIL; remPagePtr.p->prev_cluster_page= RNIL;
pageLastPtr.i = (remPagePtr.i + (1 << list)) - 1; pageLastPtr.i = (remPagePtr.i + (1 << list)) - 1;
ptrCheckGuard(pageLastPtr, cnoOfPage, cpage); c_page_pool.getPtr(pageLastPtr);
pageLastPtr.p->first_cluster_page= RNIL; pageLastPtr.p->first_cluster_page= RNIL;
}//Dbtup::removeCommonArea() }//Dbtup::removeCommonArea()

View File

@ -91,20 +91,20 @@
Uint32 Dbtup::getEmptyPage(Fragrecord* const regFragPtr) Uint32 Dbtup::getEmptyPage(Fragrecord* const regFragPtr)
{ {
Uint32 pageId = regFragPtr->emptyPrimPage; Uint32 pageId = regFragPtr->emptyPrimPage.firstItem;
if (pageId == RNIL) { if (pageId == RNIL) {
ljam(); ljam();
allocMoreFragPages(regFragPtr); allocMoreFragPages(regFragPtr);
pageId = regFragPtr->emptyPrimPage; pageId = regFragPtr->emptyPrimPage.firstItem;
if (pageId == RNIL) { if (pageId == RNIL) {
ljam(); ljam();
return RNIL; return RNIL;
}//if }//if
}//if }//if
PagePtr pagePtr; PagePtr pagePtr;
pagePtr.i = pageId; LocalDLList<Page> alloc_pages(c_page_pool, regFragPtr->emptyPrimPage);
ptrCheckGuard(pagePtr, cnoOfPage, cpage); alloc_pages.getPtr(pagePtr, pageId);
regFragPtr->emptyPrimPage = pagePtr.p->next_page; alloc_pages.remove(pagePtr);
return pageId; return pageId;
}//Dbtup::getEmptyPage() }//Dbtup::getEmptyPage()
@ -284,6 +284,22 @@ void Dbtup::releaseFragPages(Fragrecord* const regFragPtr)
ljam(); ljam();
ndbrequire(regPRPtr.i == regFragPtr->rootPageRange); ndbrequire(regPRPtr.i == regFragPtr->rootPageRange);
initFragRange(regFragPtr); initFragRange(regFragPtr);
for (Uint32 i = 0; i<MAX_FREE_LIST; i++)
{
LocalDLList<Page> tmp(c_page_pool, regFragPtr->free_var_page_array[i]);
tmp.remove();
}
{
LocalDLList<Page> tmp(c_page_pool, regFragPtr->emptyPrimPage);
tmp.remove();
}
{
LocalDLList<Page> tmp(c_page_pool, regFragPtr->thFreeFirst);
tmp.remove();
}
return; return;
} else { } else {
if (regPRPtr.p->type[indexPos] == ZNON_LEAF) { if (regPRPtr.p->type[indexPos] == ZNON_LEAF) {
@ -327,7 +343,6 @@ void Dbtup::initializePageRange()
void Dbtup::initFragRange(Fragrecord* const regFragPtr) void Dbtup::initFragRange(Fragrecord* const regFragPtr)
{ {
regFragPtr->emptyPrimPage = RNIL;
regFragPtr->rootPageRange = RNIL; regFragPtr->rootPageRange = RNIL;
regFragPtr->currentPageRange = RNIL; regFragPtr->currentPageRange = RNIL;
regFragPtr->noOfPages = 0; regFragPtr->noOfPages = 0;
@ -365,19 +380,32 @@ Uint32 Dbtup::allocFragPages(Fragrecord* const regFragPtr, Uint32 tafpNoAllocReq
/* THOSE PAGES TO EMPTY_MM AND LINK THEM INTO THE EMPTY */ /* THOSE PAGES TO EMPTY_MM AND LINK THEM INTO THE EMPTY */
/* PAGE LIST OF THE FRAGMENT. */ /* PAGE LIST OF THE FRAGMENT. */
/* ---------------------------------------------------------------- */ /* ---------------------------------------------------------------- */
Uint32 prev = RNIL;
for (loopPagePtr.i = retPageRef; loopPagePtr.i < loopLimit; loopPagePtr.i++) { for (loopPagePtr.i = retPageRef; loopPagePtr.i < loopLimit; loopPagePtr.i++) {
ljam(); ljam();
ptrCheckGuard(loopPagePtr, cnoOfPage, cpage); c_page_pool.getPtr(loopPagePtr);
loopPagePtr.p->page_state = ZEMPTY_MM; loopPagePtr.p->page_state = ZEMPTY_MM;
loopPagePtr.p->frag_page_id = startRange + loopPagePtr.p->frag_page_id = startRange +
(loopPagePtr.i - retPageRef); (loopPagePtr.i - retPageRef);
loopPagePtr.p->physical_page_id = loopPagePtr.i; loopPagePtr.p->physical_page_id = loopPagePtr.i;
loopPagePtr.p->next_page = loopPagePtr.i + 1; loopPagePtr.p->nextList = loopPagePtr.i + 1;
loopPagePtr.p->prevList = prev;
prev = loopPagePtr.i;
}//for }//for
loopPagePtr.i = (retPageRef + noOfPagesAllocated) - 1; loopPagePtr.i--;
ptrCheckGuard(loopPagePtr, cnoOfPage, cpage); ndbassert(loopPagePtr.p == c_page_pool.getPtr(loopPagePtr.i));
loopPagePtr.p->next_page = regFragPtr->emptyPrimPage; loopPagePtr.p->nextList = RNIL;
regFragPtr->emptyPrimPage = retPageRef;
LocalDLList<Page> alloc(c_page_pool, regFragPtr->emptyPrimPage);
if (noOfPagesAllocated > 1)
{
alloc.add(retPageRef, loopPagePtr);
}
else
{
alloc.add(loopPagePtr);
}
/* ---------------------------------------------------------------- */ /* ---------------------------------------------------------------- */
/* WAS ENOUGH PAGES ALLOCATED OR ARE MORE NEEDED. */ /* WAS ENOUGH PAGES ALLOCATED OR ARE MORE NEEDED. */
/* ---------------------------------------------------------------- */ /* ---------------------------------------------------------------- */

View File

@ -1178,6 +1178,18 @@ Dbtup::read_pseudo(Uint32 attrId,
outBuffer[2] = signal->theData[2]; outBuffer[2] = signal->theData[2];
outBuffer[3] = signal->theData[3]; outBuffer[3] = signal->theData[3];
return 4; return 4;
case AttributeHeader::ROWID:
outBuffer[0] = req_struct->frag_page_id;
outBuffer[1] = operPtr.p->m_tuple_location.m_page_idx;
return 2;
case AttributeHeader::ROW_GCI:
if (tabptr.p->m_bits & Tablerec::TR_RowGCI)
{
Uint64 tmp = * req_struct->m_tuple_ptr->get_mm_gci(tabptr.p);
memcpy(outBuffer, &tmp, sizeof(tmp));
return 2;
}
return 0;
default: default:
return 0; return 0;
} }

View File

@ -18,12 +18,20 @@
#include "Dbtup.hpp" #include "Dbtup.hpp"
#include <signaldata/AccScan.hpp> #include <signaldata/AccScan.hpp>
#include <signaldata/NextScan.hpp> #include <signaldata/NextScan.hpp>
#include <signaldata/AccLock.hpp>
#include <md5_hash.hpp>
#undef jam #undef jam
#undef jamEntry #undef jamEntry
#define jam() { jamLine(32000 + __LINE__); } #define jam() { jamLine(32000 + __LINE__); }
#define jamEntry() { jamEntryLine(32000 + __LINE__); } #define jamEntry() { jamEntryLine(32000 + __LINE__); }
#ifdef VM_TRACE
#define dbg(x) globalSignalLoggers.log x
#else
#define dbg(x)
#endif
void void
Dbtup::execACC_SCANREQ(Signal* signal) Dbtup::execACC_SCANREQ(Signal* signal)
{ {
@ -33,7 +41,7 @@ Dbtup::execACC_SCANREQ(Signal* signal)
ScanOpPtr scanPtr; ScanOpPtr scanPtr;
scanPtr.i = RNIL; scanPtr.i = RNIL;
do { do {
// find table and fragments // find table and fragment
TablerecPtr tablePtr; TablerecPtr tablePtr;
tablePtr.i = req->tableId; tablePtr.i = req->tableId;
ptrCheckGuard(tablePtr, cnoOfTablerec, tablerec); ptrCheckGuard(tablePtr, cnoOfTablerec, tablerec);
@ -43,49 +51,49 @@ Dbtup::execACC_SCANREQ(Signal* signal)
getFragmentrec(fragPtr, fragId, tablePtr.p); getFragmentrec(fragPtr, fragId, tablePtr.p);
ndbrequire(fragPtr.i != RNIL); ndbrequire(fragPtr.i != RNIL);
Fragrecord& frag = *fragPtr.p; Fragrecord& frag = *fragPtr.p;
// flags
Uint32 bits = 0;
if (frag.m_lcp_scan_op == RNIL) {
// seize from pool and link to per-fragment list // seize from pool and link to per-fragment list
Uint32 bits= 0;
if(frag.m_lcp_scan_op != RNIL)
{
bits |= ScanOp::SCAN_LCP;
ndbrequire(frag.m_lcp_scan_op == c_lcp_scan_op);
c_scanOpPool.getPtr(scanPtr, frag.m_lcp_scan_op);
}
else
{
LocalDLList<ScanOp> list(c_scanOpPool, frag.m_scanList); LocalDLList<ScanOp> list(c_scanOpPool, frag.m_scanList);
if (! list.seize(scanPtr)) if (! list.seize(scanPtr)) {
{
jam(); jam();
break; break;
} }
if (!AccScanReq::getNoDiskScanFlag(req->requestInfo)
&& tablePtr.p->m_no_of_disk_attributes)
{
bits |= ScanOp::SCAN_DD;
} }
bool mm = (bits & ScanOp::SCAN_DD);
if (tablePtr.p->m_attributes[mm].m_no_of_varsize > 0) {
bits |= ScanOp::SCAN_VS;
// disk pages have fixed page format
ndbrequire(! (bits & ScanOp::SCAN_DD));
}
if (! AccScanReq::getReadCommittedFlag(req->requestInfo)) {
if (AccScanReq::getLockMode(req->requestInfo) == 0)
bits |= ScanOp::SCAN_LOCK_SH;
else
bits |= ScanOp::SCAN_LOCK_EX;
}
} else {
jam();
ndbrequire(frag.m_lcp_scan_op == c_lcp_scan_op);
c_scanOpPool.getPtr(scanPtr, frag.m_lcp_scan_op);
bits |= ScanOp::SCAN_LCP;
if (tablePtr.p->m_attributes[MM].m_no_of_varsize > 0) {
bits |= ScanOp::SCAN_VS;
}
}
bits |= AccScanReq::getNRScanFlag(req->requestInfo) ? ScanOp::SCAN_NR : 0;
// set up scan op
new (scanPtr.p) ScanOp(); new (scanPtr.p) ScanOp();
ScanOp& scan = *scanPtr.p; ScanOp& scan = *scanPtr.p;
scan.m_state = ScanOp::First; scan.m_state = ScanOp::First;
// TODO scan disk only if any scanned attribute on disk
if(! (bits & ScanOp::SCAN_LCP))
{
/**
* Remove this until disk scan has been implemented
*/
if(tablePtr.p->m_attributes[DD].m_no_of_fixsize > 0 ||
tablePtr.p->m_attributes[DD].m_no_of_varsize > 0)
{
bits |= ScanOp::SCAN_DD;
if (tablePtr.p->m_attributes[DD].m_no_of_varsize > 0)
bits |= ScanOp::SCAN_DD_VS;
}
}
if(tablePtr.p->m_attributes[MM].m_no_of_varsize)
{
bits |= ScanOp::SCAN_VS;
}
scan.m_bits = bits; scan.m_bits = bits;
scan.m_userPtr = req->senderData; scan.m_userPtr = req->senderData;
scan.m_userRef = req->senderRef; scan.m_userRef = req->senderRef;
@ -94,18 +102,18 @@ Dbtup::execACC_SCANREQ(Signal* signal)
scan.m_fragPtrI = fragPtr.i; scan.m_fragPtrI = fragPtr.i;
scan.m_transId1 = req->transId1; scan.m_transId1 = req->transId1;
scan.m_transId2 = req->transId2; scan.m_transId2 = req->transId2;
scan.m_savePointId = req->savePointId;
// conf // conf
AccScanConf* const conf = (AccScanConf*)signal->getDataPtrSend(); AccScanConf* const conf = (AccScanConf*)signal->getDataPtrSend();
conf->scanPtr = req->senderData; conf->scanPtr = req->senderData;
conf->accPtr = scanPtr.i; conf->accPtr = scanPtr.i;
conf->flag = AccScanConf::ZNOT_EMPTY_FRAGMENT; conf->flag = AccScanConf::ZNOT_EMPTY_FRAGMENT;
sendSignal(req->senderRef, GSN_ACC_SCANCONF, signal, sendSignal(req->senderRef, GSN_ACC_SCANCONF,
AccScanConf::SignalLength, JBB); signal, AccScanConf::SignalLength, JBB);
return; return;
} while (0); } while (0);
if (scanPtr.i != RNIL) if (scanPtr.i != RNIL) {
{
jam(); jam();
releaseScanOp(scanPtr); releaseScanOp(scanPtr);
} }
@ -129,10 +137,21 @@ Dbtup::execNEXT_SCANREQ(Signal* signal)
break; break;
case NextScanReq::ZSCAN_NEXT_COMMIT: case NextScanReq::ZSCAN_NEXT_COMMIT:
jam(); jam();
break;
case NextScanReq::ZSCAN_COMMIT: case NextScanReq::ZSCAN_COMMIT:
jam(); jam();
{ if ((scan.m_bits & ScanOp::SCAN_LOCK) != 0) {
jam();
AccLockReq* const lockReq = (AccLockReq*)signal->getDataPtrSend();
lockReq->returnCode = RNIL;
lockReq->requestInfo = AccLockReq::Unlock;
lockReq->accOpPtr = req->accOperationPtr;
EXECUTE_DIRECT(DBACC, GSN_ACC_LOCKREQ,
signal, AccLockReq::UndoSignalLength);
jamEntry();
ndbrequire(lockReq->returnCode == AccLockReq::Success);
removeAccLockOp(scan, req->accOperationPtr);
}
if (req->scanFlag == NextScanReq::ZSCAN_COMMIT) {
NextScanConf* const conf = (NextScanConf*)signal->getDataPtrSend(); NextScanConf* const conf = (NextScanConf*)signal->getDataPtrSend();
conf->scanPtr = scan.m_userPtr; conf->scanPtr = scan.m_userPtr;
unsigned signalLength = 1; unsigned signalLength = 1;
@ -143,6 +162,35 @@ Dbtup::execNEXT_SCANREQ(Signal* signal)
break; break;
case NextScanReq::ZSCAN_CLOSE: case NextScanReq::ZSCAN_CLOSE:
jam(); jam();
if (scan.m_bits & ScanOp::SCAN_LOCK_WAIT) {
jam();
ndbrequire(scan.m_accLockOp != RNIL);
// use ACC_ABORTCONF to flush out any reply in job buffer
AccLockReq* const lockReq = (AccLockReq*)signal->getDataPtrSend();
lockReq->returnCode = RNIL;
lockReq->requestInfo = AccLockReq::AbortWithConf;
lockReq->accOpPtr = scan.m_accLockOp;
EXECUTE_DIRECT(DBACC, GSN_ACC_LOCKREQ,
signal, AccLockReq::UndoSignalLength);
jamEntry();
ndbrequire(lockReq->returnCode == AccLockReq::Success);
scan.m_state = ScanOp::Aborting;
return;
}
if (scan.m_state == ScanOp::Locked) {
jam();
ndbrequire(scan.m_accLockOp != RNIL);
AccLockReq* const lockReq = (AccLockReq*)signal->getDataPtrSend();
lockReq->returnCode = RNIL;
lockReq->requestInfo = AccLockReq::Unlock;
lockReq->accOpPtr = scan.m_accLockOp;
EXECUTE_DIRECT(DBACC, GSN_ACC_LOCKREQ,
signal, AccLockReq::UndoSignalLength);
jamEntry();
ndbrequire(lockReq->returnCode == AccLockReq::Success);
scan.m_accLockOp = RNIL;
}
scan.m_state = ScanOp::Aborting;
scanClose(signal, scanPtr); scanClose(signal, scanPtr);
return; return;
case NextScanReq::ZSCAN_NEXT_ABORT: case NextScanReq::ZSCAN_NEXT_ABORT:
@ -169,6 +217,7 @@ Dbtup::execACC_CHECK_SCAN(Signal* signal)
ScanOpPtr scanPtr; ScanOpPtr scanPtr;
c_scanOpPool.getPtr(scanPtr, req->accPtr); c_scanOpPool.getPtr(scanPtr, req->accPtr);
ScanOp& scan = *scanPtr.p; ScanOp& scan = *scanPtr.p;
// fragment
FragrecordPtr fragPtr; FragrecordPtr fragPtr;
fragPtr.i = scan.m_fragPtrI; fragPtr.i = scan.m_fragPtrI;
ptrCheckGuard(fragPtr, cnoOfFragrec, fragrecord); ptrCheckGuard(fragPtr, cnoOfFragrec, fragrecord);
@ -181,28 +230,162 @@ Dbtup::execACC_CHECK_SCAN(Signal* signal)
jamEntry(); jamEntry();
return; return;
} }
if (scan.m_bits & ScanOp::SCAN_LOCK_WAIT) {
jam();
// LQH asks if we are waiting for lock and we tell it to ask again
NextScanConf* const conf = (NextScanConf*)signal->getDataPtrSend();
conf->scanPtr = scan.m_userPtr;
conf->accOperationPtr = RNIL; // no tuple returned
conf->fragId = frag.fragmentId;
unsigned signalLength = 3;
// if TC has ordered scan close, it will be detected here
sendSignal(scan.m_userRef, GSN_NEXT_SCANCONF,
signal, signalLength, JBB);
return; // stop
}
if (scan.m_state == ScanOp::First) { if (scan.m_state == ScanOp::First) {
jam(); jam();
scanFirst(signal, fragPtr.p, scanPtr); scanFirst(signal, scanPtr);
} }
if (scan.m_state == ScanOp::Next) { if (scan.m_state == ScanOp::Next) {
jam(); jam();
scanNext(signal, fragPtr.p, scanPtr); bool immediate = scanNext(signal, scanPtr);
} if (! immediate) {
if (scan.m_state == ScanOp::Locked) {
jam(); jam();
const PagePos& pos = scan.m_scanPos; // time-slicing via TUP or PGMAN
return;
}
}
scanReply(signal, scanPtr);
}
void
Dbtup::scanReply(Signal* signal, ScanOpPtr scanPtr)
{
ScanOp& scan = *scanPtr.p;
FragrecordPtr fragPtr;
fragPtr.i = scan.m_fragPtrI;
ptrCheckGuard(fragPtr, cnoOfFragrec, fragrecord);
Fragrecord& frag = *fragPtr.p;
// for reading tuple key in Current state
Uint32* pkData = (Uint32*)c_dataBuffer;
unsigned pkSize = 0;
if (scan.m_state == ScanOp::Current) {
// found an entry to return
jam();
ndbrequire(scan.m_accLockOp == RNIL);
if (scan.m_bits & ScanOp::SCAN_LOCK) {
jam();
// read tuple key - use TUX routine
const ScanPos& pos = scan.m_scanPos;
const Local_key& key_mm = pos.m_key_mm;
int ret = tuxReadPk(fragPtr.i, pos.m_realpid_mm, key_mm.m_page_idx,
pkData, false);
ndbrequire(ret > 0);
pkSize = ret;
dbg((DBTUP, "PK size=%d data=%08x", pkSize, pkData[0]));
// get read lock or exclusive lock
AccLockReq* const lockReq = (AccLockReq*)signal->getDataPtrSend();
lockReq->returnCode = RNIL;
lockReq->requestInfo = (scan.m_bits & ScanOp::SCAN_LOCK_SH) ?
AccLockReq::LockShared : AccLockReq::LockExclusive;
lockReq->accOpPtr = RNIL;
lockReq->userPtr = scanPtr.i;
lockReq->userRef = reference();
lockReq->tableId = scan.m_tableId;
lockReq->fragId = frag.fragmentId;
lockReq->fragPtrI = RNIL; // no cached frag ptr yet
lockReq->hashValue = md5_hash((Uint64*)pkData, pkSize);
lockReq->tupAddr = key_mm.ref();
lockReq->transId1 = scan.m_transId1;
lockReq->transId2 = scan.m_transId2;
EXECUTE_DIRECT(DBACC, GSN_ACC_LOCKREQ,
signal, AccLockReq::LockSignalLength);
jamEntry();
switch (lockReq->returnCode) {
case AccLockReq::Success:
jam();
scan.m_state = ScanOp::Locked;
scan.m_accLockOp = lockReq->accOpPtr;
break;
case AccLockReq::IsBlocked:
jam();
// normal lock wait
scan.m_state = ScanOp::Blocked;
scan.m_bits |= ScanOp::SCAN_LOCK_WAIT;
scan.m_accLockOp = lockReq->accOpPtr;
// LQH will wake us up
signal->theData[0] = scan.m_userPtr;
signal->theData[1] = true;
EXECUTE_DIRECT(DBLQH, GSN_CHECK_LCP_STOP, signal, 2);
jamEntry();
return;
break;
case AccLockReq::Refused:
jam();
// we cannot see deleted tuple (assert only)
ndbassert(false);
// skip it
scan.m_state = ScanOp::Next;
signal->theData[0] = scan.m_userPtr;
signal->theData[1] = true;
EXECUTE_DIRECT(DBLQH, GSN_CHECK_LCP_STOP, signal, 2);
jamEntry();
return;
break;
case AccLockReq::NoFreeOp:
jam();
// max ops should depend on max scans (assert only)
ndbassert(false);
// stay in Current state
scan.m_state = ScanOp::Current;
signal->theData[0] = scan.m_userPtr;
signal->theData[1] = true;
EXECUTE_DIRECT(DBLQH, GSN_CHECK_LCP_STOP, signal, 2);
jamEntry();
return;
break;
default:
ndbrequire(false);
break;
}
} else {
scan.m_state = ScanOp::Locked;
}
}
if (scan.m_state == ScanOp::Locked) {
// we have lock or do not need one
jam();
// conf signal
NextScanConf* const conf = (NextScanConf*)signal->getDataPtrSend(); NextScanConf* const conf = (NextScanConf*)signal->getDataPtrSend();
conf->scanPtr = scan.m_userPtr; conf->scanPtr = scan.m_userPtr;
conf->accOperationPtr = (Uint32)-1; // no lock returned // the lock is passed to LQH
Uint32 accLockOp = scan.m_accLockOp;
if (accLockOp != RNIL) {
scan.m_accLockOp = RNIL;
// remember it until LQH unlocks it
addAccLockOp(scan, accLockOp);
} else {
ndbrequire(! (scan.m_bits & ScanOp::SCAN_LOCK));
// operation RNIL in LQH would signal no tuple returned
accLockOp = (Uint32)-1;
}
const ScanPos& pos = scan.m_scanPos;
conf->accOperationPtr = accLockOp;
conf->fragId = frag.fragmentId; conf->fragId = frag.fragmentId;
conf->localKey[0] = pos.m_key.ref(); conf->localKey[0] = pos.m_key_mm.ref();
conf->localKey[1] = 0; conf->localKey[1] = 0;
conf->localKeyLength = 1; conf->localKeyLength = 1;
unsigned signalLength = 6; unsigned signalLength = 6;
if (scan.m_bits & ScanOp::SCAN_LOCK) {
sendSignal(scan.m_userRef, GSN_NEXT_SCANCONF,
signal, signalLength, JBB);
} else {
Uint32 blockNo = refToBlock(scan.m_userRef); Uint32 blockNo = refToBlock(scan.m_userRef);
EXECUTE_DIRECT(blockNo, GSN_NEXT_SCANCONF, signal, signalLength); EXECUTE_DIRECT(blockNo, GSN_NEXT_SCANCONF, signal, signalLength);
jamEntry(); jamEntry();
}
// next time look for next entry // next time look for next entry
scan.m_state = ScanOp::Next; scan.m_state = ScanOp::Next;
return; return;
@ -222,122 +405,491 @@ Dbtup::execACC_CHECK_SCAN(Signal* signal)
ndbrequire(false); ndbrequire(false);
} }
/*
* Lock succeeded (after delay) in ACC. If the lock is for current
* entry, set state to Locked. If the lock is for an entry we were
* moved away from, simply unlock it. Finally, if we are closing the
* scan, do nothing since we have already sent an abort request.
*/
void void
Dbtup::scanFirst(Signal*, Fragrecord* fragPtrP, ScanOpPtr scanPtr) Dbtup::execACCKEYCONF(Signal* signal)
{ {
jamEntry();
ScanOpPtr scanPtr;
scanPtr.i = signal->theData[0];
c_scanOpPool.getPtr(scanPtr);
ScanOp& scan = *scanPtr.p; ScanOp& scan = *scanPtr.p;
// set to first fragment, first page, first tuple ndbrequire(scan.m_bits & ScanOp::SCAN_LOCK_WAIT && scan.m_accLockOp != RNIL);
const Uint32 first_page_idx = scan.m_bits & ScanOp::SCAN_VS ? 1 : 0; scan.m_bits &= ~ ScanOp::SCAN_LOCK_WAIT;
PagePos& pos = scan.m_scanPos; if (scan.m_state == ScanOp::Blocked) {
pos.m_key.m_page_no = 0; // the lock wait was for current entry
pos.m_key.m_page_idx = first_page_idx; jam();
// just before scan.m_state = ScanOp::Locked;
pos.m_match = false; // LQH has the ball
// let scanNext() do the work return;
scan.m_state = ScanOp::Next;
if (scan.m_bits & ScanOp::SCAN_DD)
{
pos.m_extent_info_ptr_i =
fragPtrP->m_disk_alloc_info.m_extent_list.firstItem;
} }
if (scan.m_state != ScanOp::Aborting) {
// we were moved, release lock
jam();
AccLockReq* const lockReq = (AccLockReq*)signal->getDataPtrSend();
lockReq->returnCode = RNIL;
lockReq->requestInfo = AccLockReq::Unlock;
lockReq->accOpPtr = scan.m_accLockOp;
EXECUTE_DIRECT(DBACC, GSN_ACC_LOCKREQ, signal, AccLockReq::UndoSignalLength);
jamEntry();
ndbrequire(lockReq->returnCode == AccLockReq::Success);
scan.m_accLockOp = RNIL;
// LQH has the ball
return;
}
// lose the lock
scan.m_accLockOp = RNIL;
// continue at ACC_ABORTCONF
}
/*
* Lock failed (after delay) in ACC. Probably means somebody ahead of
* us in lock queue deleted the tuple.
*/
void
Dbtup::execACCKEYREF(Signal* signal)
{
jamEntry();
ScanOpPtr scanPtr;
scanPtr.i = signal->theData[0];
c_scanOpPool.getPtr(scanPtr);
ScanOp& scan = *scanPtr.p;
ndbrequire(scan.m_bits & ScanOp::SCAN_LOCK_WAIT && scan.m_accLockOp != RNIL);
scan.m_bits &= ~ ScanOp::SCAN_LOCK_WAIT;
if (scan.m_state != ScanOp::Aborting) {
jam();
// release the operation
AccLockReq* const lockReq = (AccLockReq*)signal->getDataPtrSend();
lockReq->returnCode = RNIL;
lockReq->requestInfo = AccLockReq::Abort;
lockReq->accOpPtr = scan.m_accLockOp;
EXECUTE_DIRECT(DBACC, GSN_ACC_LOCKREQ, signal, AccLockReq::UndoSignalLength);
jamEntry();
ndbrequire(lockReq->returnCode == AccLockReq::Success);
scan.m_accLockOp = RNIL;
// scan position should already have been moved (assert only)
if (scan.m_state == ScanOp::Blocked) {
jam();
//ndbassert(false);
if (scan.m_bits & ScanOp::SCAN_NR)
{
jam();
scan.m_state = ScanOp::Next;
scan.m_scanPos.m_get = ScanPos::Get_tuple;
ndbout_c("Ignoring scan.m_state == ScanOp::Blocked, refetch");
}
else
{
jam();
scan.m_state = ScanOp::Next;
ndbout_c("Ignoring scan.m_state == ScanOp::Blocked");
}
}
// LQH has the ball
return;
}
// lose the lock
scan.m_accLockOp = RNIL;
// continue at ACC_ABORTCONF
}
/*
* Received when scan is closing. This signal arrives after any
* ACCKEYCON or ACCKEYREF which may have been in job buffer.
*/
void
Dbtup::execACC_ABORTCONF(Signal* signal)
{
jamEntry();
ScanOpPtr scanPtr;
scanPtr.i = signal->theData[0];
c_scanOpPool.getPtr(scanPtr);
ScanOp& scan = *scanPtr.p;
ndbrequire(scan.m_state == ScanOp::Aborting);
// most likely we are still in lock wait
if (scan.m_bits & ScanOp::SCAN_LOCK_WAIT) {
jam();
scan.m_bits &= ~ ScanOp::SCAN_LOCK_WAIT;
scan.m_accLockOp = RNIL;
}
scanClose(signal, scanPtr);
} }
void void
Dbtup::scanNext(Signal* signal, Fragrecord* fragPtrP, ScanOpPtr scanPtr) Dbtup::scanFirst(Signal*, ScanOpPtr scanPtr)
{ {
ScanOp& scan = *scanPtr.p; ScanOp& scan = *scanPtr.p;
PagePos& pos = scan.m_scanPos; ScanPos& pos = scan.m_scanPos;
Uint32 bits = scan.m_bits;
Local_key& key = pos.m_key; Local_key& key = pos.m_key;
const Uint32 bits = scan.m_bits;
// fragment
FragrecordPtr fragPtr;
fragPtr.i = scan.m_fragPtrI;
ptrCheckGuard(fragPtr, cnoOfFragrec, fragrecord);
Fragrecord& frag = *fragPtr.p;
// in the future should not pre-allocate pages
if (frag.noOfPages == 0) {
jam();
scan.m_state = ScanOp::Last;
return;
}
if (! (bits & ScanOp::SCAN_DD)) {
key.m_file_no = ZNIL;
key.m_page_no = 0;
pos.m_get = ScanPos::Get_page_mm;
// for MM scan real page id is cached for efficiency
pos.m_realpid_mm = RNIL;
} else {
Disk_alloc_info& alloc = frag.m_disk_alloc_info;
// for now must check disk part explicitly
if (alloc.m_extent_list.firstItem == RNIL) {
jam();
scan.m_state = ScanOp::Last;
return;
}
pos.m_extent_info_ptr_i = alloc.m_extent_list.firstItem;
Extent_info* ext = c_extent_pool.getPtr(pos.m_extent_info_ptr_i);
key.m_file_no = ext->m_key.m_file_no;
key.m_page_no = ext->m_first_page_no;
pos.m_get = ScanPos::Get_page_dd;
}
key.m_page_idx = 0;
// let scanNext() do the work
scan.m_state = ScanOp::Next;
}
bool
Dbtup::scanNext(Signal* signal, ScanOpPtr scanPtr)
{
ScanOp& scan = *scanPtr.p;
ScanPos& pos = scan.m_scanPos;
Local_key& key = pos.m_key;
const Uint32 bits = scan.m_bits;
// table
TablerecPtr tablePtr; TablerecPtr tablePtr;
tablePtr.i = scan.m_tableId; tablePtr.i = scan.m_tableId;
ptrCheckGuard(tablePtr, cnoOfTablerec, tablerec); ptrCheckGuard(tablePtr, cnoOfTablerec, tablerec);
Fragrecord& frag = *fragPtrP; Tablerec& table = *tablePtr.p;
const Uint32 first_page_idx = bits & ScanOp::SCAN_VS ? 1 : 0; // fragment
FragrecordPtr fragPtr;
fragPtr.i = scan.m_fragPtrI;
ptrCheckGuard(fragPtr, cnoOfFragrec, fragrecord);
Fragrecord& frag = *fragPtr.p;
// tuple found
Tuple_header* th = 0;
Uint32 loop_count = 0;
Uint32 scanGCI = scanPtr.p->m_scanGCI;
Uint32 foundGCI;
bool mm = (bits & ScanOp::SCAN_DD);
Uint32 size = table.m_offsets[mm].m_fix_header_size +
(bits & ScanOp::SCAN_VS ? Tuple_header::HeaderSize + 1: 0);
while (true) { while (true) {
// TODO time-slice here after X loops switch (pos.m_get) {
case ScanPos::Get_next_page:
// move to next page
jam(); jam();
// get page {
PagePtr pagePtr; if (! (bits & ScanOp::SCAN_DD))
pos.m_get = ScanPos::Get_next_page_mm;
else
pos.m_get = ScanPos::Get_next_page_dd;
}
continue;
case ScanPos::Get_page:
// get real page
jam();
{
if (! (bits & ScanOp::SCAN_DD))
pos.m_get = ScanPos::Get_page_mm;
else
pos.m_get = ScanPos::Get_page_dd;
}
continue;
case ScanPos::Get_next_page_mm:
// move to next logical TUP page
jam();
{
key.m_page_no++;
if (key.m_page_no >= frag.noOfPages) { if (key.m_page_no >= frag.noOfPages) {
jam(); jam();
// no more pages, scan ends
pos.m_get = ScanPos::Get_undef;
scan.m_state = ScanOp::Last; scan.m_state = ScanOp::Last;
break; return true;
} }
Uint32 realPageId = getRealpid(fragPtrP, key.m_page_no); key.m_page_idx = 0;
pagePtr.i = realPageId; pos.m_get = ScanPos::Get_page_mm;
ptrCheckGuard(pagePtr, cnoOfPage, cpage); // clear cached value
Uint32 pageState = pagePtr.p->page_state; pos.m_realpid_mm = RNIL;
}
/*FALLTHRU*/
case ScanPos::Get_page_mm:
// get TUP real page
jam();
{
if (pos.m_realpid_mm == RNIL) {
jam();
pos.m_realpid_mm = getRealpid(fragPtr.p, key.m_page_no);
}
PagePtr pagePtr;
c_page_pool.getPtr(pagePtr, pos.m_realpid_mm);
if (pagePtr.p->page_state == ZEMPTY_MM) {
// skip empty page // skip empty page
if (pageState == ZEMPTY_MM) {
jam(); jam();
key.m_page_no++; pos.m_get = ScanPos::Get_next_page_mm;
key.m_page_idx = first_page_idx; break; // incr loop count
pos.m_match = false;
continue;
} }
// get next tuple pos.m_page = pagePtr.p;
const Tuple_header* th = 0; pos.m_get = ScanPos::Get_tuple;
if (! (bits & ScanOp::SCAN_VS)) {
Uint32 tupheadsize = tablePtr.p->m_offsets[MM].m_fix_header_size;
if (pos.m_match)
key.m_page_idx += tupheadsize;
pos.m_match = true;
if (key.m_page_idx + tupheadsize > Fix_page::DATA_WORDS) {
jam();
key.m_page_no++;
key.m_page_idx = first_page_idx;
pos.m_match = false;
continue;
} }
th = (Tuple_header*)&pagePtr.p->m_data[key.m_page_idx];
// skip over free tuple
if (th->m_header_bits & Tuple_header::FREE) {
jam();
continue; continue;
case ScanPos::Get_next_page_dd:
// move to next disk page
jam();
{
Disk_alloc_info& alloc = frag.m_disk_alloc_info;
LocalSLList<Extent_info, Extent_list_t>
list(c_extent_pool, alloc.m_extent_list);
Ptr<Extent_info> ext_ptr;
c_extent_pool.getPtr(ext_ptr, pos.m_extent_info_ptr_i);
Extent_info* ext = ext_ptr.p;
key.m_page_no++;
if (key.m_page_no >= ext->m_first_page_no + alloc.m_extent_size) {
// no more pages in this extent
jam();
if (! list.next(ext_ptr)) {
// no more extents, scan ends
jam();
pos.m_get = ScanPos::Get_undef;
scan.m_state = ScanOp::Last;
return true;
} else {
// move to next extent
jam();
pos.m_extent_info_ptr_i = ext_ptr.i;
Extent_info* ext = c_extent_pool.getPtr(pos.m_extent_info_ptr_i);
key.m_file_no = ext->m_key.m_file_no;
key.m_page_no = ext->m_first_page_no;
}
}
key.m_page_idx = 0;
pos.m_get = ScanPos::Get_page_dd;
}
/*FALLTHRU*/
case ScanPos::Get_page_dd:
// get global page in PGMAN cache
jam();
{
// check if page is un-allocated or empty
if (likely(! (bits & ScanOp::SCAN_NR)))
{
Tablespace_client tsman(signal, c_tsman,
frag.fragTableId,
frag.fragmentId,
frag.m_tablespace_id);
unsigned bits = ~(unsigned)0;
int ret = tsman.get_page_free_bits(&key, &bits);
ndbrequire(ret == 0);
if (bits == 0) {
// skip empty page
jam();
pos.m_get = ScanPos::Get_next_page_dd;
break; // incr loop count
}
}
// page request to PGMAN
Page_cache_client::Request preq;
preq.m_page = pos.m_key;
preq.m_callback.m_callbackData = scanPtr.i;
preq.m_callback.m_callbackFunction =
safe_cast(&Dbtup::disk_page_tup_scan_callback);
int flags = Page_cache_client::STRICT_ORDER;
int res = m_pgman.get_page(signal, preq, flags);
if (res == 0) {
jam();
// request queued
pos.m_get = ScanPos::Get_tuple;
return false;
}
ndbrequire(res > 0);
pos.m_page = (Page*)m_pgman.m_ptr.p;
}
pos.m_get = ScanPos::Get_tuple;
continue;
// get tuple
// move to next tuple
case ScanPos::Get_next_tuple:
case ScanPos::Get_next_tuple_fs:
// move to next fixed size tuple
jam();
{
key.m_page_idx += size;
pos.m_get = ScanPos::Get_tuple_fs;
}
/*FALLTHRU*/
case ScanPos::Get_tuple:
case ScanPos::Get_tuple_fs:
// get fixed size tuple
jam();
{
Fix_page* page = (Fix_page*)pos.m_page;
if (key.m_page_idx + size <= Fix_page::DATA_WORDS)
{
pos.m_get = ScanPos::Get_next_tuple_fs;
th = (Tuple_header*)&page->m_data[key.m_page_idx];
if (likely(! (bits & ScanOp::SCAN_NR)))
{
if (! (th->m_header_bits & Tuple_header::FREE)) {
goto found_tuple;
}
else
{
jam();
// skip free tuple
}
}
else
{
if ((foundGCI = *th->get_mm_gci(tablePtr.p)) > scanGCI)
{
if (! (th->m_header_bits & Tuple_header::FREE))
{
jam();
goto found_tuple;
}
else
{
goto found_deleted_rowid;
}
}
else
{
jam();
// skip free tuple
}
} }
} else { } else {
Var_page* page_ptr = (Var_page*)pagePtr.p;
if (pos.m_match)
key.m_page_idx += 1;
pos.m_match = true;
if (key.m_page_idx >= page_ptr->high_index) {
jam(); jam();
key.m_page_no++; // no more tuples on this page
key.m_page_idx = first_page_idx; pos.m_get = ScanPos::Get_next_page;
pos.m_match = false;
continue;
} }
}
break; // incr loop count
found_tuple:
// found possible tuple to return
jam();
{
// caller has already set pos.m_get to next tuple
if (! (bits & ScanOp::SCAN_LCP &&
th->m_header_bits & Tuple_header::LCP_SKIP)) {
Local_key& key_mm = pos.m_key_mm;
if (! (bits & ScanOp::SCAN_DD)) {
key_mm = pos.m_key;
// real page id is already set
} else {
key_mm.assref(th->m_base_record_ref);
// recompute for each disk tuple
pos.m_realpid_mm = getRealpid(fragPtr.p, key_mm.m_page_no);
}
// TUPKEYREQ handles savepoint stuff
scan.m_state = ScanOp::Current;
return true;
} else {
jam();
// clear it so that it will show up in next LCP
th->m_header_bits &= ~(Uint32)Tuple_header::LCP_SKIP;
}
}
break;
found_deleted_rowid:
jam();
{
ndbassert(bits & ScanOp::SCAN_NR);
Local_key& key_mm = pos.m_key_mm;
Fix_page* page = (Fix_page*)pos.m_page;
if (! (bits & ScanOp::SCAN_DD)) {
key_mm = pos.m_key;
// caller has already set pos.m_get to next tuple
// real page id is already set
} else {
key_mm.assref(th->m_base_record_ref);
// recompute for each disk tuple
pos.m_realpid_mm = getRealpid(fragPtr.p, key_mm.m_page_no);
Uint32 len= page_ptr->get_entry_len(key.m_page_idx); Fix_page *mmpage = (Fix_page*)c_page_pool.getPtr(pos.m_realpid_mm);
if (len == 0) th = (Tuple_header*)(mmpage->m_data + key_mm.m_page_idx);
if ((foundGCI = *th->get_mm_gci(tablePtr.p)) > scanGCI)
{ {
// skip empty slot or if (! (th->m_header_bits & Tuple_header::FREE))
jam();
continue;
}
if(len & Var_page::CHAIN)
{
// skip varpart chain
jam();
continue;
}
th = (Tuple_header*)page_ptr->get_ptr(key.m_page_idx);
}
if(bits & ScanOp::SCAN_LCP &&
th->m_header_bits & Tuple_header::LCP_SKIP)
{
/**
* Clear it so that it will show up in next LCP
*/
((Tuple_header*)th)->m_header_bits &= ~(Uint32)Tuple_header::LCP_SKIP;
continue;
}
scan.m_state = ScanOp::Locked;
break; break;
} }
}
NextScanConf* const conf = (NextScanConf*)signal->getDataPtrSend();
conf->scanPtr = scan.m_userPtr;
conf->accOperationPtr = RNIL;
conf->fragId = frag.fragmentId;
conf->localKey[0] = pos.m_key_mm.ref();
conf->localKey[1] = 0;
conf->localKeyLength = 1;
conf->gci = foundGCI;
Uint32 blockNo = refToBlock(scan.m_userRef);
EXECUTE_DIRECT(blockNo, GSN_NEXT_SCANCONF, signal, 7);
jamEntry();
// TUPKEYREQ handles savepoint stuff
loop_count = 32;
scan.m_state = ScanOp::Next;
return false;
}
break; // incr loop count
default:
ndbrequire(false);
break;
}
if (++loop_count >= 32)
break;
}
// TODO: at drop table we have to flush and terminate these
jam();
signal->theData[0] = ZTUP_SCAN;
signal->theData[1] = scanPtr.i;
sendSignal(reference(), GSN_CONTINUEB, signal, 2, JBB);
return false;
}
void
Dbtup::scanCont(Signal* signal, ScanOpPtr scanPtr)
{
bool immediate = scanNext(signal, scanPtr);
if (! immediate) {
jam();
// time-slicing again
return;
}
scanReply(signal, scanPtr);
}
void
Dbtup::disk_page_tup_scan_callback(Signal* signal, Uint32 scanPtrI, Uint32 page_i)
{
ScanOpPtr scanPtr;
c_scanOpPool.getPtr(scanPtr, scanPtrI);
ScanOp& scan = *scanPtr.p;
ScanPos& pos = scan.m_scanPos;
// get cache page
Ptr<GlobalPage> gptr;
m_global_page_pool.getPtr(gptr, page_i);
pos.m_page = (Page*)gptr.p;
// continue
scanCont(signal, scanPtr);
} }
void void
@ -350,10 +902,43 @@ Dbtup::scanClose(Signal* signal, ScanOpPtr scanPtr)
unsigned signalLength = 3; unsigned signalLength = 3;
sendSignal(scanPtr.p->m_userRef, GSN_NEXT_SCANCONF, sendSignal(scanPtr.p->m_userRef, GSN_NEXT_SCANCONF,
signal, signalLength, JBB); signal, signalLength, JBB);
releaseScanOp(scanPtr); releaseScanOp(scanPtr);
} }
void
Dbtup::addAccLockOp(ScanOp& scan, Uint32 accLockOp)
{
LocalDLFifoList<ScanLock> list(c_scanLockPool, scan.m_accLockOps);
ScanLockPtr lockPtr;
#ifdef VM_TRACE
list.first(lockPtr);
while (lockPtr.i != RNIL) {
ndbrequire(lockPtr.p->m_accLockOp != accLockOp);
list.next(lockPtr);
}
#endif
bool ok = list.seize(lockPtr);
ndbrequire(ok);
lockPtr.p->m_accLockOp = accLockOp;
}
void
Dbtup::removeAccLockOp(ScanOp& scan, Uint32 accLockOp)
{
LocalDLFifoList<ScanLock> list(c_scanLockPool, scan.m_accLockOps);
ScanLockPtr lockPtr;
list.first(lockPtr);
while (lockPtr.i != RNIL) {
if (lockPtr.p->m_accLockOp == accLockOp) {
jam();
break;
}
list.next(lockPtr);
}
ndbrequire(lockPtr.i != RNIL);
list.release(lockPtr);
}
void void
Dbtup::releaseScanOp(ScanOpPtr& scanPtr) Dbtup::releaseScanOp(ScanOpPtr& scanPtr)
{ {
@ -396,8 +981,9 @@ Dbtup::execLCP_FRAG_ORD(Signal* signal)
frag.m_lcp_scan_op = c_lcp_scan_op; frag.m_lcp_scan_op = c_lcp_scan_op;
ScanOpPtr scanPtr; ScanOpPtr scanPtr;
c_scanOpPool.getPtr(scanPtr, frag.m_lcp_scan_op); c_scanOpPool.getPtr(scanPtr, frag.m_lcp_scan_op);
//ndbrequire(scanPtr.p->m_fragPtrI == fragPtr.i); ?
scanFirst(signal, fragPtr.p, scanPtr); scanFirst(signal, scanPtr);
scanPtr.p->m_state = ScanOp::First; scanPtr.p->m_state = ScanOp::First;
} }
} }

View File

@ -581,6 +581,11 @@ Dbtup::fireDetachedTriggers(KeyReqStruct *req_struct,
regOperPtr->op_struct.op_type = ZUPDATE; regOperPtr->op_struct.op_type = ZUPDATE;
} }
/**
* Set disk page
*/
req_struct->m_disk_page_ptr.i = m_pgman.m_ptr.i;
ndbrequire(regOperPtr->is_first_operation()); ndbrequire(regOperPtr->is_first_operation());
triggerList.first(trigPtr); triggerList.first(trigPtr);
while (trigPtr.i != RNIL) { while (trigPtr.i != RNIL) {
@ -817,8 +822,8 @@ bool Dbtup::readTriggerInfo(TupTriggerData* const trigPtr,
//-------------------------------------------------------------------- //--------------------------------------------------------------------
// Read Primary Key Values // Read Primary Key Values
//-------------------------------------------------------------------- //--------------------------------------------------------------------
if (regTabPtr->need_expand(false)) // no disk if (regTabPtr->need_expand())
prepare_read(req_struct, regTabPtr, false); // setup varsize prepare_read(req_struct, regTabPtr, true);
int ret = readAttributes(req_struct, int ret = readAttributes(req_struct,
&tableDescriptor[regTabPtr->readKeyArray].tabDescr, &tableDescriptor[regTabPtr->readKeyArray].tabDescr,
@ -902,8 +907,8 @@ bool Dbtup::readTriggerInfo(TupTriggerData* const trigPtr,
req_struct->m_tuple_ptr= (Tuple_header*)ptr; req_struct->m_tuple_ptr= (Tuple_header*)ptr;
} }
if (regTabPtr->need_expand(false)) // no disk if (regTabPtr->need_expand()) // no disk
prepare_read(req_struct, regTabPtr, false); // setup varsize prepare_read(req_struct, regTabPtr, true);
int ret = readAttributes(req_struct, int ret = readAttributes(req_struct,
&readBuffer[0], &readBuffer[0],
@ -1168,7 +1173,7 @@ Dbtup::executeTuxCommitTriggers(Signal* signal,
req->pageIndex = regOperPtr->m_tuple_location.m_page_idx; req->pageIndex = regOperPtr->m_tuple_location.m_page_idx;
req->tupVersion = tupVersion; req->tupVersion = tupVersion;
req->opInfo = TuxMaintReq::OpRemove; req->opInfo = TuxMaintReq::OpRemove;
removeTuxEntries(signal, regOperPtr, regTabPtr); removeTuxEntries(signal, regTabPtr);
} }
void void
@ -1200,12 +1205,11 @@ Dbtup::executeTuxAbortTriggers(Signal* signal,
req->pageIndex = regOperPtr->m_tuple_location.m_page_idx; req->pageIndex = regOperPtr->m_tuple_location.m_page_idx;
req->tupVersion = tupVersion; req->tupVersion = tupVersion;
req->opInfo = TuxMaintReq::OpRemove; req->opInfo = TuxMaintReq::OpRemove;
removeTuxEntries(signal, regOperPtr, regTabPtr); removeTuxEntries(signal, regTabPtr);
} }
void void
Dbtup::removeTuxEntries(Signal* signal, Dbtup::removeTuxEntries(Signal* signal,
Operationrec* regOperPtr,
Tablerec* regTabPtr) Tablerec* regTabPtr)
{ {
TuxMaintReq* const req = (TuxMaintReq*)signal->getDataPtrSend(); TuxMaintReq* const req = (TuxMaintReq*)signal->getDataPtrSend();

View File

@ -39,394 +39,6 @@ void Dbtup::init_list_sizes(void)
c_max_list_size[4]= 199; c_max_list_size[4]= 199;
} }
#if 0
void
Dbtup::free_separate_var_part(Fragrecord* const regFragPtr,
Tablerec* const regTabPtr,
Tuple_header* tuple_header)
{
Uint32 page_ref, page_index;
PagePtr page_ptr;
page_ref= tuple_header->m_data[regTabPtr->var_offset];
page_index= page_ref & MAX_TUPLES_PER_PAGE;
page_ptr.i= page_ref >> MAX_TUPLES_BITS;
ptrCheckGuard(page_ptr, cnoOfPage, cpage);
free_var_rec(regFragPtr,
regTabPtr,
(Var_page*)page_ptr.p,
page_index);
}
void
Dbtup::abort_separate_var_part(Uint32 var_page_ref,
const Uint32* copy_var_part,
Uint32 copy_var_size)
{
Uint32 page_index;
PagePtr var_page_ptr;
page_index= var_page_ref & MAX_TUPLES_PER_PAGE;
var_page_ptr.i= var_page_ref >> MAX_TUPLES_BITS;
ptrCheckGuard(var_page_ptr, cnoOfPage, cpage);
Uint32 *ptr= ((Var_page*)var_page_ptr.p)->get_ptr(page_index);
MEMCOPY_NO_WORDS(ptr, copy_var_part, copy_var_size);
}
void
Dbtup::shrink_entry(Fragrecord* const regFragPtr,
Var_page* const page_ptr,
Uint32 page_index,
Uint32 new_size)
{
page_ptr->shrink_entry(page_index, new_size);
update_free_page_list(regFragPtr, page_ptr);
}
void
Dbtup::check_entry_size(KeyReqStruct* req_struct,
Operationrec* regOperPtr,
Fragrecord* const regFragPtr,
Tablerec* const regTabPtr)
{
#if 0
Uint32 vp_index, no_var_attr, total_var_size, add_size, new_size, entry_len;
Uint32 vp_offset, tuple_size, var_part_local;
Uint32 *var_data_part, *var_link;
PagePtr var_page_ptr;
Uint32* tuple_ptr= req_struct->m_tuple_ptr;
Uint32 page_index= regOperPtr->m_tuple_location.m_page_idx;
tuple_size= regTabPtr->tupheadsize;
no_var_attr= regTabPtr->no_var_attr;
var_part_local= get_var_part_local(* (tuple_ptr+1));
add_size= regTabPtr->var_array_wsize;
var_link= tuple_ptr+tuple_size;
if (var_part_local == 1) {
ljam();
var_data_part= var_link;
var_page_ptr.p= req_struct->fix_page_ptr.p;
add_size+= tuple_size;
vp_index= regOperPtr->m_tuple_location.m_page_idx;
} else {
ljam();
entry_len= get_entry_len(req_struct->var_page_ptr, page_index);
if (entry_len > (tuple_size + 1)) {
ljam();
shrink_entry(regFragPtr,
req_struct->fix_page_ptr,
page_index,
tuple_size + 1);
} else {
ndbassert(entry_len == (tuple_size + 1));
}
set_up_var_page(*var_link,
regFragPtr,
var_page_ptr,
vp_index,
vp_offset);
var_data_part= &var_page_ptr.p->pageWord[vp_offset];
}
total_var_size= calculate_total_var_size((uint16*)var_data_part,
no_var_attr);
new_size= total_var_size + add_size;
entry_len= get_entry_len(var_page_ptr.p, vp_index);
if (new_size < entry_len) {
ljam();
shrink_entry(regFragPtr,
var_page_ptr.p,
vp_index,
new_size);
} else {
ndbassert(entry_len == new_size);
}
#endif
}
inline
void
Dbtup::grow_entry(Fragrecord* const regFragPtr,
Var_page* page_header,
Uint32 page_index,
Uint32 growth_len)
{
page_header->grow_entry(page_index, growth_len);
update_free_page_list(regFragPtr, page_header);
}
void
Dbtup::setup_varsize_part(KeyReqStruct* req_struct,
Operationrec* const regOperPtr,
Tablerec* const regTabPtr)
{
Uint32 num_var_attr;
Uint32 var_data_wsize;
Uint32* var_data_ptr;
Uint32* var_data_start;
Uint32 page_index= regOperPtr->m_tuple_location.m_page_idx;
if (regTabPtr->var_sized_record) {
ljam();
num_var_attr= regTabPtr->no_var_attr;
if (!(req_struct->m_tuple_ptr->m_header_bits & Tuple_header::CHAINED_ROW))
{
ljam();
var_data_ptr= req_struct->m_tuple_ptr->m_data+regTabPtr->var_offset;
req_struct->var_page_ptr.i = req_struct->fix_page_ptr.i;
req_struct->var_page_ptr.p = (Var_page*)req_struct->fix_page_ptr.p;
req_struct->vp_index= page_index;
} else {
Uint32 var_link= req_struct->m_tuple_ptr->m_data[regTabPtr->var_offset];
ljam();
Uint32 vp_index= var_link & MAX_TUPLES_PER_PAGE;
PagePtr var_page_ptr;
var_page_ptr.i= var_link >> MAX_TUPLES_BITS;
ptrCheckGuard(var_page_ptr, cnoOfPage, cpage);
req_struct->vp_index= vp_index;
req_struct->var_page_ptr.i= var_page_ptr.i;
req_struct->var_page_ptr.p= (Var_page*)var_page_ptr.p;
var_data_ptr= ((Var_page*)var_page_ptr.p)->get_ptr(vp_index);
req_struct->fix_var_together= false;
}
var_data_start= &var_data_ptr[regTabPtr->var_array_wsize];
req_struct->var_len_array= (Uint16*)var_data_ptr;
req_struct->var_data_start= var_data_start;
var_data_wsize= init_var_pos_array(req_struct->var_len_array,
&req_struct->var_pos_array[0],
num_var_attr);
req_struct->var_data_end= &var_data_start[var_data_wsize];
}
}
bool
Dbtup::compress_var_sized_part_after_update(KeyReqStruct *req_struct,
Operationrec* const regOperPtr,
Fragrecord* const regFragPtr,
Tablerec* const regTabPtr)
{
Uint32 entry_len, old_var_len, new_size, total_size;
Uint32* used_var_data_start= req_struct->var_data_start;
total_size= calculate_total_var_size(req_struct->var_len_array,
regTabPtr->no_var_attr);
entry_len= req_struct->var_page_ptr.p->get_entry_len(req_struct->vp_index);
if (req_struct->fix_var_together) {
ljam();
old_var_len= entry_len -
(regTabPtr->tupheadsize + regTabPtr->var_array_wsize);
} else {
ljam();
old_var_len= entry_len - regTabPtr->var_array_wsize;
}
if (total_size > old_var_len) {
ljam();
/**
* The new total size of the variable part is greater than it was before
* the update. We will need to increase the size of the record or split
* it into a fixed part and a variable part.
*/
if (! handle_growth_after_update(req_struct,
regFragPtr,
regTabPtr,
(total_size - old_var_len))) {
ljam();
return false;
}
} else if (total_size < old_var_len) {
ljam();
/**
* The new total size is smaller than what it was before we started.
* In one case we can shrink immediately and this is after an initial
* insert since we allocate in this case a full sized tuple and there
* is no problem in shrinking this already before committing.
*
* For all other cases we need to keep the space to ensure that we
* can safely abort (which means in this case to grow back to
* original size). Thus shrink cannot be done before commit occurs
* in those cases.
*/
if (regOperPtr->op_struct.op_type == ZINSERT &&
regOperPtr->prevActiveOp == RNIL &&
regOperPtr->nextActiveOp == RNIL) {
ljam();
new_size= entry_len - (old_var_len - total_size);
shrink_entry(regFragPtr,
req_struct->var_page_ptr.p,
req_struct->vp_index,
new_size);
}
}
reset_req_struct_data(regTabPtr,
req_struct,
regOperPtr->m_tuple_location.m_page_idx);
copy_back_var_attr(req_struct, regTabPtr, used_var_data_start);
return true;
}
void
Dbtup::reset_req_struct_data(Tablerec* const regTabPtr,
KeyReqStruct* req_struct,
Uint32 fix_index)
{
Var_page *var_page_ptr, *fix_page_ptr;
Uint32 vp_index;
fix_page_ptr= (Var_page*)req_struct->fix_page_ptr.p;
var_page_ptr= req_struct->var_page_ptr.p;
vp_index= req_struct->vp_index;
req_struct->m_tuple_ptr= (Tuple_header*)fix_page_ptr->get_ptr(fix_index);
Uint32 vp_len= var_page_ptr->get_entry_len(vp_index);
Uint32 *var_ptr;
if (req_struct->fix_var_together)
{
ljam();
var_ptr= req_struct->m_tuple_ptr->m_data+regTabPtr->var_offset;
}
else
{
var_ptr= var_page_ptr->get_ptr(vp_index);
}
req_struct->var_len_array= (Uint16*)(var_ptr);
req_struct->var_data_start= var_ptr+regTabPtr->var_array_wsize;
req_struct->var_data_end= var_ptr+regTabPtr->var_array_wsize+vp_len;
}
void
Dbtup::copy_back_var_attr(KeyReqStruct *req_struct,
Tablerec* const regTabPtr,
Uint32 *source_rec)
{
Uint32 i, dest_index, vpos_index, byte_size, word_size, num_var_attr;
Uint32 *dest_rec, max_var_size, entry_len;
Uint32 total_word_size= 0;
#ifdef VM_TRACE
entry_len= req_struct->var_page_ptr.p->get_entry_len(req_struct->vp_index);
if (req_struct->fix_var_together) {
ljam();
max_var_size= entry_len - (regTabPtr->tupheadsize +
regTabPtr->var_array_wsize);
} else {
ljam();
max_var_size= entry_len - regTabPtr->var_array_wsize;
}
#endif
dest_rec= req_struct->var_data_start;
num_var_attr= regTabPtr->no_var_attr;
ljam();
for (i= 0; i < num_var_attr; i++) {
dest_index= total_word_size;
byte_size= req_struct->var_len_array[i];
vpos_index= req_struct->var_pos_array[i];
word_size= convert_byte_to_word_size(byte_size);
total_word_size+= word_size;
req_struct->var_pos_array[i]= total_word_size;
MEMCOPY_NO_WORDS(&dest_rec[vpos_index],
&source_rec[dest_index],
word_size);
ndbassert((vpos_index + word_size) <= max_var_size);
}
ndbassert(total_word_size <= max_var_size);
req_struct->var_pos_array[num_var_attr]= total_word_size;
req_struct->var_data_end= &req_struct->var_data_start[total_word_size];
}
void
Dbtup::copy_out_var_attr(KeyReqStruct *req_struct,
Tablerec* const regTabPtr)
{
Uint32 i, source_index, byte_size, vpos_index, word_size, last_pos_array;
Uint32 num_var_attr= regTabPtr->no_var_attr;
Uint16 copy_pos_array[MAX_ATTRIBUTES_IN_TABLE + 1];
init_var_len_array(&copy_pos_array[0], regTabPtr);
init_var_pos_array(&copy_pos_array[0],
&copy_pos_array[0],
regTabPtr->no_var_attr);
Uint32 *source_rec= req_struct->var_data_start;
Uint32 *dest_rec= &ctemp_var_record[0];
Uint32 total_word_size= 0;
ljam();
for (i= 0; i < num_var_attr; i++) {
source_index= total_word_size;
byte_size= req_struct->var_len_array[i];
vpos_index= copy_pos_array[i];
word_size= convert_byte_to_word_size(byte_size);
total_word_size+= word_size;
req_struct->var_pos_array[i]= copy_pos_array[i];
MEMCOPY_NO_WORDS(&dest_rec[source_index],
&source_rec[vpos_index],
word_size);
}
last_pos_array= copy_pos_array[num_var_attr];
req_struct->var_data_start= dest_rec;
req_struct->var_data_end= &dest_rec[last_pos_array];
req_struct->var_part_updated= true;
req_struct->var_pos_array[num_var_attr]= last_pos_array;
}
Uint32
Dbtup::calculate_total_var_size(Uint16* var_len_array,
Uint32 num_var_attr)
{
Uint32 i, byte_size, word_size, total_size;
total_size= 0;
for (i= 0; i < num_var_attr; i++) {
byte_size= var_len_array[i];
word_size= convert_byte_to_word_size(byte_size);
total_size+= word_size;
}
return total_size;
}
Uint32
Dbtup::init_var_pos_array(Uint16* var_len_array,
Uint16* var_pos_array,
Uint32 num_var_attr)
{
Uint32 i, real_len, word_len;
Uint32 curr_pos= 0;
for (i= 0, curr_pos= 0; i < num_var_attr; i++) {
real_len= var_len_array[i];
var_pos_array[i]= curr_pos;
word_len= convert_byte_to_word_size(real_len);
curr_pos+= word_len;
}
var_pos_array[num_var_attr]= curr_pos;
return curr_pos;
}
void
Dbtup::init_var_len_array(Uint16 *var_len_array, Tablerec *tab_ptr)
{
Uint32 array_ind= 0;
Uint32 attr_descr, i;
Uint32 no_of_attr= tab_ptr->noOfAttr;
Uint32 descr_start= tab_ptr->tabDescriptor;
TableDescriptor *tab_descr= &tableDescriptor[descr_start];
ndbrequire(descr_start + (no_of_attr << ZAD_LOG_SIZE) <= cnoOfTabDescrRec);
for (i= 0; i < no_of_attr; i++) {
attr_descr= tab_descr[i * ZAD_SIZE].tabDescr;
if (AttributeDescriptor::getArrayType(attr_descr) == 0) {
Uint32 bits_used= AttributeDescriptor::getArraySize(attr_descr) *
(1 << AttributeDescriptor::getSize(attr_descr));
Uint32 no_attr_bytes= ((bits_used + 7) >> 3);
var_len_array[array_ind++]= no_attr_bytes;
}
}
}
#endif
/* /*
Allocator for variable sized segments Allocator for variable sized segments
Part of the external interface for variable sized segments Part of the external interface for variable sized segments
@ -438,8 +50,8 @@ Dbtup::init_var_len_array(Uint16 *var_len_array, Tablerec *tab_ptr)
and dropping attributes without the need to copy the entire table. and dropping attributes without the need to copy the entire table.
SYNOPSIS SYNOPSIS
frag_ptr A pointer to the fragment description fragPtr A pointer to the fragment description
tab_ptr A pointer to the table description tabPtr A pointer to the table description
alloc_size Size of the allocated record alloc_size Size of the allocated record
signal The signal object to be used if a signal needs to signal The signal object to be used if a signal needs to
be sent be sent
@ -451,44 +63,81 @@ Dbtup::init_var_len_array(Uint16 *var_len_array, Tablerec *tab_ptr)
page_ptr The i and p value of the page where the record was page_ptr The i and p value of the page where the record was
allocated allocated
*/ */
Uint32* Dbtup::alloc_var_rec(Fragrecord* const frag_ptr, Uint32* Dbtup::alloc_var_rec(Fragrecord* fragPtr,
Tablerec* const tab_ptr, Tablerec* tabPtr,
Uint32 alloc_size, Uint32 alloc_size,
Local_key* key, Local_key* key,
Uint32 * out_frag_page_id, Uint32 * out_frag_page_id)
Uint32 base)
{ {
Var_page* page_header; /**
PagePtr page_ptr; * TODO alloc fix+var part
page_ptr.i= get_alloc_page(frag_ptr, (alloc_size + 1)); */
if (page_ptr.i == RNIL) { tabPtr->m_offsets[MM].m_fix_header_size += Tuple_header::HeaderSize + 1;
Uint32 *ptr = alloc_fix_rec(fragPtr, tabPtr, key, out_frag_page_id);
tabPtr->m_offsets[MM].m_fix_header_size -= Tuple_header::HeaderSize + 1;
if (unlikely(ptr == 0))
{
return 0;
}
ndbassert(alloc_size >= tabPtr->m_offsets[MM].m_fix_header_size +
Tuple_header::HeaderSize);
alloc_size -= tabPtr->m_offsets[MM].m_fix_header_size +
Tuple_header::HeaderSize;
Local_key varref;
if (likely(alloc_var_part(fragPtr, tabPtr, alloc_size, &varref) != 0))
{
Tuple_header* tuple = (Tuple_header*)ptr;
* tuple->get_var_part_ptr(tabPtr) = varref.ref();
return ptr;
}
PagePtr pagePtr;
c_page_pool.getPtr(pagePtr, key->m_page_no);
free_fix_rec(fragPtr, tabPtr, key, (Fix_page*)pagePtr.p);
return 0;
}
Uint32*
Dbtup::alloc_var_part(Fragrecord* fragPtr,
Tablerec* tabPtr,
Uint32 alloc_size,
Local_key* key)
{
PagePtr pagePtr;
pagePtr.i= get_alloc_page(fragPtr, (alloc_size + 1));
if (pagePtr.i == RNIL) {
ljam(); ljam();
if ((page_ptr.i= getEmptyPage(frag_ptr)) == RNIL) { if ((pagePtr.i= get_empty_var_page(fragPtr)) == RNIL) {
ljam(); ljam();
return 0; return 0;
} }
ptrCheckGuard(page_ptr, cnoOfPage, cpage); c_page_pool.getPtr(pagePtr);
page_header= (Var_page*)page_ptr.p; ((Var_page*)pagePtr.p)->init();
page_header->init(); pagePtr.p->list_index = MAX_FREE_LIST - 1;
insert_free_page(frag_ptr, page_header, MAX_FREE_LIST - 1); LocalDLList<Page> list(c_page_pool,
fragPtr->free_var_page_array[MAX_FREE_LIST-1]);
list.add(pagePtr);
/* /*
* Tup scan and index build check ZEMPTY_MM to skip un-init()ed * Tup scan and index build check ZEMPTY_MM to skip un-init()ed
* page. Change state here. For varsize it means "page in use". * page. Change state here. For varsize it means "page in use".
*/ */
page_ptr.p->page_state = ZTH_MM_FREE; pagePtr.p->page_state = ZTH_MM_FREE;
} else { } else {
ptrCheckGuard(page_ptr, cnoOfPage, cpage); c_page_pool.getPtr(pagePtr);
ljam(); ljam();
page_header= (Var_page*)page_ptr.p;
} }
Uint32 idx= page_header->alloc_record(alloc_size, Uint32 idx= ((Var_page*)pagePtr.p)
(Var_page*)ctemp_page, base); ->alloc_record(alloc_size, (Var_page*)ctemp_page, Var_page::CHAIN);
key->m_page_no= page_ptr.i; key->m_page_no = pagePtr.i;
key->m_page_idx= idx; key->m_page_idx = idx;
*out_frag_page_id= page_header->frag_page_id;
update_free_page_list(frag_ptr, page_header); update_free_page_list(fragPtr, pagePtr);
return page_header->get_ptr(idx); return ((Var_page*)pagePtr.p)->get_ptr(idx);
} }
/* /*
@ -496,8 +145,8 @@ Uint32* Dbtup::alloc_var_rec(Fragrecord* const frag_ptr,
Part of the external interface for variable sized segments Part of the external interface for variable sized segments
SYNOPSIS SYNOPSIS
frag_ptr A pointer to the fragment description fragPtr A pointer to the fragment description
tab_ptr A pointer to the table description tabPtr A pointer to the table description
signal The signal object to be used if a signal needs to signal The signal object to be used if a signal needs to
be sent be sent
page_ptr A reference to the page of the variable sized page_ptr A reference to the page of the variable sized
@ -507,102 +156,59 @@ Uint32* Dbtup::alloc_var_rec(Fragrecord* const frag_ptr,
RETURN VALUES RETURN VALUES
Returns true if deallocation was successful otherwise false Returns true if deallocation was successful otherwise false
*/ */
void void Dbtup::free_var_rec(Fragrecord* fragPtr,
Dbtup::free_var_part(Fragrecord* frag_ptr, Tablerec* tab_ptr, Tablerec* tabPtr,
Var_part_ref ref, Uint32 chain)
{
Local_key tmp;
PagePtr pagePtr;
tmp.m_page_idx= ref.m_ref & MAX_TUPLES_PER_PAGE;
pagePtr.i= tmp.m_page_no= ref.m_ref >> MAX_TUPLES_BITS;
ptrCheckGuard(pagePtr, cnoOfPage, cpage);
free_var_part(frag_ptr, tab_ptr, &tmp, (Var_page*)pagePtr.p, chain);
}
void Dbtup::free_var_part(Fragrecord* const frag_ptr,
Tablerec* const tab_ptr,
Local_key* key, Local_key* key,
Var_page* const page_header, Ptr<Page> pagePtr)
Uint32 chain)
{ {
/**
* TODO free fix + var part
*/
Uint32 page_idx= key->m_page_idx; Uint32 page_idx= key->m_page_idx;
page_header->free_record(page_idx, chain); Uint32 *ptr = ((Fix_page*)pagePtr.p)->get_ptr(key->m_page_idx, 0);
Tuple_header* tuple = (Tuple_header*)ptr;
ndbassert(page_header->free_space <= Var_page::DATA_WORDS); Local_key ref;
if (page_header->free_space == Var_page::DATA_WORDS - 1) ref.assref(* tuple->get_var_part_ptr(tabPtr));
free_fix_rec(fragPtr, tabPtr, key, (Fix_page*)pagePtr.p);
c_page_pool.getPtr(pagePtr, ref.m_page_no);
((Var_page*)pagePtr.p)->free_record(ref.m_page_idx, Var_page::CHAIN);
ndbassert(pagePtr.p->free_space <= Var_page::DATA_WORDS);
if (pagePtr.p->free_space == Var_page::DATA_WORDS - 1)
{ {
ljam(); ljam();
/* /*
This code could be used when we release pages. This code could be used when we release pages.
remove_free_page(signal,frag_ptr,page_header,page_header->list_index); remove_free_page(signal,fragPtr,page_header,page_header->list_index);
return_empty_page(frag_ptr, page_header); return_empty_page(fragPtr, page_header);
*/ */
update_free_page_list(frag_ptr, page_header); update_free_page_list(fragPtr, pagePtr);
} else { } else {
ljam(); ljam();
update_free_page_list(frag_ptr, page_header); update_free_page_list(fragPtr, pagePtr);
} }
return; return;
} }
int
#if 0 Dbtup::realloc_var_part(Fragrecord* fragPtr, Tablerec* tabPtr, PagePtr pagePtr,
/* Var_part_ref* ref, Uint32 oldsz, Uint32 newsz)
This method is called whenever the variable part has been updated and
has grown beyond its original size. This means that more space needs to
be allocated to the record. If possible this space should be in the
same page but we might have to allocate more space in a new page.
In the case of a new page we must still keep the old page and the
page index since this is the entrance to the record. In this case the
record might have to be split into a fixed part and a variable part.
This routine uses cinBuffer as temporary copy buffer. This is no longer
used since it contains the interpreted program to use in the update
and this has completed when this function is called.
SYNOPSIS
req_struct The structure for temporary content
signal The signal object
regOperPtr The operation record
regFragPtr The fragment record
regTabPtr The table record
RETURN VALUES
bool false if failed due to lack of memory
*/
bool
Dbtup::handle_growth_after_update(KeyReqStruct* req_struct,
Fragrecord* const regFragPtr,
Tablerec* const regTabPtr,
Uint32 growth_len)
{ {
Uint32 vp_index, alloc_size, entry_len, curr_var_len; Uint32 add = newsz - oldsz;
Uint32 new_vp_index, new_vp_offset, new_page_ref; Var_page* pageP = (Var_page*)pagePtr.p;
Uint32 *copy_record= &cinBuffer[0]; Local_key oldref;
Ptr<Var_page> var_page= req_struct->var_page_ptr; oldref.assref(*(Uint32*)ref);
Var_page* page_header= var_page.p;
vp_index= req_struct->vp_index; if (pageP->free_space >= add)
entry_len= var_page.p->get_entry_len(vp_index); {
if (page_header->free_space >= growth_len) { jam();
/** if(!pageP->is_space_behind_entry(oldref.m_page_idx, add))
* We will be able to handle the growth without changing the page {
* and page index. if(0) printf("extra reorg");
*/ jam();
if (page_header->largest_frag_size() >= entry_len + growth_len) {
ljam();
/**
* In this case we need to copy the entry to the free space area of
* the page, it is not necessary to reorganise the page.
*/
MEMCOPY_NO_WORDS(page_header->get_free_space_ptr(),
page_header->get_ptr(vp_index),
entry_len);
page_header->set_entry_offset(vp_index, page_header->insert_pos);
page_header->insert_pos+= entry_len;
} else {
ljam();
/** /**
* In this case we need to reorganise the page to fit. To ensure we * In this case we need to reorganise the page to fit. To ensure we
* don't complicate matters we make a little trick here where we * don't complicate matters we make a little trick here where we
@ -610,97 +216,48 @@ Dbtup::handle_growth_after_update(KeyReqStruct* req_struct,
* that separately at the end. This means we need to copy it out of * that separately at the end. This means we need to copy it out of
* the page before reorg_page to save the entry contents. * the page before reorg_page to save the entry contents.
*/ */
MEMCOPY_NO_WORDS(copy_record, Uint32* copyBuffer= cinBuffer;
page_header->get_ptr(vp_index), memcpy(copyBuffer, pageP->get_ptr(oldref.m_page_idx), 4*oldsz);
entry_len); pageP->set_entry_len(oldref.m_page_idx, 0);
page_header->set_entry_len(vp_index, 0); pageP->free_space += oldsz;
page_header->free_space+= entry_len; pageP->reorg((Var_page*)ctemp_page);
reorg_page(page_header); memcpy(pageP->get_free_space_ptr(), copyBuffer, 4*oldsz);
MEMCOPY_NO_WORDS(page_header->get_free_space_ptr(), pageP->set_entry_offset(oldref.m_page_idx, pageP->insert_pos);
copy_record, add += oldsz;
entry_len);
page_header->set_entry_offset(vp_index, page_header->insert_pos);
growth_len+= entry_len;
} }
grow_entry(regFragPtr, pageP->grow_entry(oldref.m_page_idx, add);
page_header, update_free_page_list(fragPtr, pagePtr);
vp_index,
growth_len);
return true;
} else {
/**
* It is necessary to allocate a segment from a new page.
*/
if (req_struct->fix_var_together) {
ljam();
alloc_size= (entry_len + growth_len) - regTabPtr->tupheadsize;
curr_var_len= alloc_size - regTabPtr->var_array_wsize;
} else {
ljam();
curr_var_len= entry_len - regTabPtr->var_array_wsize;
alloc_size= entry_len + growth_len;
} }
Uint32* ptr, frag_page_id; else
Local_key key;
if ((ptr= alloc_var_rec(regFragPtr,
regTabPtr,
alloc_size,
&key, &frag_page_id)) == 0)
{ {
/** Local_key newref;
* No space existed for this growth. We need to abort the update. Uint32 *src = pageP->get_ptr(oldref.m_page_idx);
*/ Uint32 *dst = alloc_var_part(fragPtr, tabPtr, newsz, &newref);
ljam(); if (unlikely(dst == 0))
terrorCode= ZMEM_NOMEM_ERROR; return -1;
return false;
ndbassert(oldref.m_page_no != newref.m_page_no);
ndbassert(pageP->get_entry_len(oldref.m_page_idx) == oldsz);
memcpy(dst, src, 4*oldsz);
* ((Uint32*)ref) = newref.ref();
pageP->free_record(oldref.m_page_idx, Var_page::CHAIN);
update_free_page_list(fragPtr, pagePtr);
} }
/* return 0;
* I need to be careful to copy the var_len_array before freeing it.
* The data part will be copied by copy_back_var_attr immediately
* after returning from this method.
* The updated var part is always in ctemp_var_record since I can
* never arrive here after a first insert. Thus no danger of the
* var part written being released.
*/
MEMCOPY_NO_WORDS(ptr,
req_struct->var_len_array,
regTabPtr->var_array_wsize);
req_struct->var_len_array= (Uint16*)ptr;
if (! req_struct->fix_var_together) {
ljam();
/*
* We need to deallocate the old variable part. This new one will
* remain the variable part even if we abort the transaction.
* We don't keep multiple references to the variable parts.
* The copy data for abort is still kept in the copy record.
*/
free_separate_var_part(regFragPtr, regTabPtr, req_struct->m_tuple_ptr);
} else {
ljam();
req_struct->fix_var_together= false;
}
page_header= (Var_page*)var_page.p;
new_page_ref= (key.m_page_no << MAX_TUPLES_BITS) + key.m_page_idx;
req_struct->m_tuple_ptr->m_data[regTabPtr->var_offset] = new_page_ref;
Uint32 bits= req_struct->m_tuple_ptr->m_header_bits;
req_struct->m_tuple_ptr->m_header_bits |= Tuple_header::CHAINED_ROW;
req_struct->var_page_ptr= var_page;
req_struct->vp_index= key.m_page_idx;
}
return true;
} }
#endif
/* ------------------------------------------------------------------------ */ /* ------------------------------------------------------------------------ */
// Get a page from one of free lists. If the desired free list is empty we // Get a page from one of free lists. If the desired free list is empty we
// try with the next until we have tried all possible lists. // try with the next until we have tried all possible lists.
/* ------------------------------------------------------------------------ */ /* ------------------------------------------------------------------------ */
Uint32 Dbtup::get_alloc_page(Fragrecord* const frag_ptr, Uint32 alloc_size) Uint32
Dbtup::get_alloc_page(Fragrecord* fragPtr, Uint32 alloc_size)
{ {
Uint32 i, start_index, loop_count= 0; Uint32 i, start_index, loop= 0;
PagePtr page_ptr; PagePtr pagePtr;
start_index= calculate_free_list_impl(alloc_size); start_index= calculate_free_list_impl(alloc_size);
if (start_index == (MAX_FREE_LIST - 1)) { if (start_index == (MAX_FREE_LIST - 1)) {
@ -712,37 +269,73 @@ Uint32 Dbtup::get_alloc_page(Fragrecord* const frag_ptr, Uint32 alloc_size)
} }
for (i= start_index; i < MAX_FREE_LIST; i++) { for (i= start_index; i < MAX_FREE_LIST; i++) {
ljam(); ljam();
if (frag_ptr->free_var_page_array[i] != RNIL) { if (!fragPtr->free_var_page_array[i].isEmpty()) {
ljam(); ljam();
return frag_ptr->free_var_page_array[i]; return fragPtr->free_var_page_array[i].firstItem;
} }
} }
ndbrequire(start_index > 0); ndbrequire(start_index > 0);
i= start_index - 1; i= start_index - 1;
page_ptr.i= frag_ptr->free_var_page_array[i]; LocalDLList<Page> list(c_page_pool, fragPtr->free_var_page_array[i]);
while ((page_ptr.i != RNIL) && (loop_count++ < 16)) { for(list.first(pagePtr); !pagePtr.isNull() && loop < 16; )
{
ljam(); ljam();
ptrCheckGuard(page_ptr, cnoOfPage, cpage); if (pagePtr.p->free_space >= alloc_size) {
Var_page* page_header= (Var_page*)page_ptr.p;
if (page_header->free_space >= alloc_size) {
ljam(); ljam();
return page_ptr.i; return pagePtr.i;
} }
page_ptr.i= page_header->next_page; loop++;
list.next(pagePtr);
} }
return RNIL; return RNIL;
} }
Uint32
Dbtup::get_empty_var_page(Fragrecord* fragPtr)
{
PagePtr ptr;
LocalSLList<Page> list(c_page_pool, fragPtr->m_empty_pages);
if (list.remove_front(ptr))
{
return ptr.i;
}
Uint32 cnt;
allocConsPages(10, cnt, ptr.i);
if (unlikely(cnt == 0))
{
return RNIL;
}
PagePtr ret = ptr;
for (Uint32 i = 0; i<cnt; i++, ptr.i++)
{
c_page_pool.getPtr(ptr);
ptr.p->physical_page_id = ptr.i;
ptr.p->page_state = ZEMPTY_MM;
ptr.p->nextList = ptr.i + 1;
ptr.p->prevList = RNIL;
ptr.p->frag_page_id = RNIL;
}
if (cnt > 1)
{
ptr.p->nextList = RNIL;
list.add(ret.i + 1, ptr);
}
return ret.i;
}
/* ------------------------------------------------------------------------ */ /* ------------------------------------------------------------------------ */
// Check if the page needs to go to a new free page list. // Check if the page needs to go to a new free page list.
/* ------------------------------------------------------------------------ */ /* ------------------------------------------------------------------------ */
void Dbtup::update_free_page_list(Fragrecord* const frag_ptr, void Dbtup::update_free_page_list(Fragrecord* fragPtr,
Var_page* page_header) Ptr<Page> pagePtr)
{ {
Uint32 free_space, list_index; Uint32 free_space, list_index;
free_space= page_header->free_space; free_space= pagePtr.p->free_space;
list_index= page_header->list_index; list_index= pagePtr.p->list_index;
if ((free_space < c_min_list_size[list_index]) || if ((free_space < c_min_list_size[list_index]) ||
(free_space > c_max_list_size[list_index])) { (free_space > c_max_list_size[list_index])) {
Uint32 new_list_index= calculate_free_list_impl(free_space); Uint32 new_list_index= calculate_free_list_impl(free_space);
@ -751,25 +344,30 @@ void Dbtup::update_free_page_list(Fragrecord* const frag_ptr,
/* /*
* Only remove it from its list if it is in a list * Only remove it from its list if it is in a list
*/ */
remove_free_page(frag_ptr, page_header, list_index); LocalDLList<Page>
list(c_page_pool, fragPtr->free_var_page_array[list_index]);
list.remove(pagePtr);
} }
if (free_space < c_min_list_size[new_list_index]) { if (free_space < c_min_list_size[new_list_index]) {
/* /*
We have not sufficient amount of free space to put it into any We have not sufficient amount of free space to put it into any
free list. Thus the page will not be available for new inserts. free list. Thus the page will not be available for new inserts.
This can only happen for the free list with least guaranteed free space. This can only happen for the free list with least guaranteed
free space.
*/ */
ljam(); ljam();
ndbrequire(new_list_index == 0); ndbrequire(new_list_index == 0);
page_header->list_index= MAX_FREE_LIST; pagePtr.p->list_index= MAX_FREE_LIST;
} else { } else {
ljam(); ljam();
insert_free_page(frag_ptr, page_header, new_list_index); LocalDLList<Page> list(c_page_pool,
fragPtr->free_var_page_array[new_list_index]);
list.add(pagePtr);
pagePtr.p->list_index = new_list_index;
} }
} }
} }
/* ------------------------------------------------------------------------ */ /* ------------------------------------------------------------------------ */
// Given size of free space, calculate the free list to put it into // Given size of free space, calculate the free list to put it into
/* ------------------------------------------------------------------------ */ /* ------------------------------------------------------------------------ */
@ -787,60 +385,37 @@ Uint32 Dbtup::calculate_free_list_impl(Uint32 free_space_size) const
return 0; return 0;
} }
Uint32*
/* ------------------------------------------------------------------------ */ Dbtup::alloc_var_rowid(Fragrecord* fragPtr,
// Remove a page from its current free list Tablerec* tabPtr,
/* ------------------------------------------------------------------------ */ Uint32 alloc_size,
void Dbtup::remove_free_page(Fragrecord* frag_ptr, Local_key* key,
Var_page* page_header, Uint32 * out_frag_page_id)
Uint32 index)
{ {
Var_page* tmp_page_header; tabPtr->m_offsets[MM].m_fix_header_size += Tuple_header::HeaderSize + 1;
if (page_header->prev_page == RNIL) { Uint32 *ptr = alloc_fix_rowid(fragPtr, tabPtr, key, out_frag_page_id);
ljam(); tabPtr->m_offsets[MM].m_fix_header_size -= Tuple_header::HeaderSize + 1;
ndbassert(index < MAX_FREE_LIST); if (unlikely(ptr == 0))
frag_ptr->free_var_page_array[index]= page_header->next_page; {
} else { return 0;
ljam();
PagePtr prev_page_ptr;
prev_page_ptr.i= page_header->prev_page;
ptrCheckGuard(prev_page_ptr, cnoOfPage, cpage);
tmp_page_header= (Var_page*)prev_page_ptr.p;
tmp_page_header->next_page= page_header->next_page;
} }
if (page_header->next_page != RNIL) {
ljam(); ndbassert(alloc_size >= tabPtr->m_offsets[MM].m_fix_header_size +
PagePtr next_page_ptr; Tuple_header::HeaderSize);
next_page_ptr.i= page_header->next_page;
ptrCheckGuard(next_page_ptr, cnoOfPage, cpage); alloc_size -= tabPtr->m_offsets[MM].m_fix_header_size +
tmp_page_header= (Var_page*) next_page_ptr.p; Tuple_header::HeaderSize;
tmp_page_header->prev_page= page_header->prev_page;
Local_key varref;
if (likely(alloc_var_part(fragPtr, tabPtr, alloc_size, &varref) != 0))
{
Tuple_header* tuple = (Tuple_header*)ptr;
* tuple->get_var_part_ptr(tabPtr) = varref.ref();
return ptr;
} }
PagePtr pagePtr;
c_page_pool.getPtr(pagePtr, key->m_page_no);
free_fix_rec(fragPtr, tabPtr, key, (Fix_page*)pagePtr.p);
return 0;
} }
/* ------------------------------------------------------------------------ */
// Insert a page into a free list on the fragment
/* ------------------------------------------------------------------------ */
void Dbtup::insert_free_page(Fragrecord* frag_ptr,
Var_page* page_header,
Uint32 index)
{
Var_page* tmp_page_header;
Uint32 current_head= frag_ptr->free_var_page_array[index];
Uint32 pagePtrI = page_header->physical_page_id;
page_header->next_page= current_head;
ndbassert(index < MAX_FREE_LIST);
frag_ptr->free_var_page_array[index]= pagePtrI;
page_header->prev_page= RNIL;
page_header->list_index= index;
if (current_head != RNIL) {
ljam();
PagePtr head_page_ptr;
head_page_ptr.i= current_head;
ptrCheckGuard(head_page_ptr, cnoOfPage, cpage);
tmp_page_header= (Var_page*)head_page_ptr.p;
tmp_page_header->prev_page= pagePtrI;
}
}

View File

@ -50,15 +50,13 @@ Undo_buffer::alloc_copy_tuple(Local_key* dst, Uint32 words)
m_tup->allocConsPages(1, count, m_first_free); m_tup->allocConsPages(1, count, m_first_free);
if(count == 0) if(count == 0)
return 0; return 0;
page= (UndoPage*)(m_tup->cpage+m_first_free); page= (UndoPage*)m_tup->c_page_pool.getPtr(m_first_free);
page->m_state= ~ZFREE_COMMON; page->m_state= ~ZFREE_COMMON;
page->m_words_used= 0; page->m_words_used= 0;
page->m_ref_count= 0; page->m_ref_count= 0;
} }
if(m_first_free < m_tup->cnoOfPage) page= (UndoPage*)m_tup->c_page_pool.getPtr(m_first_free);
{
page= (UndoPage*)(m_tup->cpage+m_first_free);
Uint32 pos= page->m_words_used; Uint32 pos= page->m_words_used;
if(words + pos > UndoPage::DATA_WORDS) if(words + pos > UndoPage::DATA_WORDS)
@ -73,16 +71,13 @@ Undo_buffer::alloc_copy_tuple(Local_key* dst, Uint32 words)
page->m_ref_count++; page->m_ref_count++;
page->m_words_used = pos + words; page->m_words_used = pos + words;
return page->m_data + pos; return page->m_data + pos;
}
assert(false);
return 0;
} }
void void
Undo_buffer::shrink_copy_tuple(Local_key* key, Uint32 words) Undo_buffer::shrink_copy_tuple(Local_key* key, Uint32 words)
{ {
assert(key->m_page_no == m_first_free); assert(key->m_page_no == m_first_free);
UndoPage* page= (UndoPage*)(m_tup->cpage+key->m_page_no); UndoPage* page= (UndoPage*)m_tup->c_page_pool.getPtr(key->m_page_no);
assert(page->m_words_used >= words); assert(page->m_words_used >= words);
page->m_words_used -= words; page->m_words_used -= words;
} }
@ -90,7 +85,7 @@ Undo_buffer::shrink_copy_tuple(Local_key* key, Uint32 words)
void void
Undo_buffer::free_copy_tuple(Local_key* key) Undo_buffer::free_copy_tuple(Local_key* key)
{ {
UndoPage* page= (UndoPage*)(m_tup->cpage+key->m_page_no); UndoPage* page= (UndoPage*)m_tup->c_page_pool.getPtr(key->m_page_no);
Uint32 cnt= page->m_ref_count; Uint32 cnt= page->m_ref_count;
assert(cnt); assert(cnt);
@ -115,6 +110,6 @@ Undo_buffer::free_copy_tuple(Local_key* key)
Uint32 * Uint32 *
Undo_buffer::get_ptr(Local_key* key) Undo_buffer::get_ptr(Local_key* key)
{ {
return ((UndoPage*)(m_tup->cpage+key->m_page_no))->m_data+key->m_page_idx; return ((UndoPage*)(m_tup->c_page_pool.getPtr(key->m_page_no)))->m_data+key->m_page_idx;
} }

View File

@ -9,14 +9,21 @@ struct Record
Uint32* data; Uint32* data;
}; };
NdbOut&
operator <<(NdbOut& out, const Record& rec)
{
out << "[ idx: " << rec.idx << " sz: " << rec.size << " ]";
return out;
}
#define TRACE(x) x #define TRACE(x) x
static static
void bool
cmp(const Uint32 *p1, const Uint32 *p2, Uint32 words) cmp(const Uint32 *p1, const Uint32 *p2, Uint32 words)
{ {
if(memcmp(p1, p2, 4*words) == 0) if(memcmp(p1, p2, 4*words) == 0)
return; return true;
for(Uint32 i = 0; i<words; i++) for(Uint32 i = 0; i<words; i++)
printf(" %.8x", p1[i]); printf(" %.8x", p1[i]);
@ -26,13 +33,20 @@ cmp(const Uint32 *p1, const Uint32 *p2, Uint32 words)
printf(" %.8x", p2[i]); printf(" %.8x", p2[i]);
printf("\n"); printf("\n");
abort(); return false;
} }
static static
void void
do_test(int loops, int dist[3]) do_test(int loops, int dist[5])
{ {
fprintf(stderr, "do_test(%d, [ %d %d %d %d %d ])\n",
loops,
dist[0],
dist[1],
dist[2],
dist[3],
dist[4]);
int allocated= 0; int allocated= 0;
Record records[8192]; Record records[8192];
@ -41,17 +55,32 @@ do_test(int loops, int dist[3])
for(int i = 0; i<loops; i++) for(int i = 0; i<loops; i++)
{ {
assert(page.high_index + page.insert_pos <= page.DATA_WORDS);
for(int j = 0; j<allocated; j++) for(int j = 0; j<allocated; j++)
{ {
Record rec= records[j]; Record rec= records[j];
Uint32* ptr= page.get_ptr(rec.idx); Uint32* ptr= page.get_ptr(rec.idx);
cmp(ptr, rec.data, rec.size); Uint32 pos = page.get_ptr(rec.idx) - page.m_data;
if (page.get_entry_len(rec.idx) != rec.size)
{
ndbout << "INVALID LEN " << j << " " << rec << " pos: " << pos << endl;
ndbout << page << endl;
abort();
}
if(!cmp(ptr, rec.data, rec.size))
{
ndbout << "FAILED " << j << " " << rec << " pos: " << pos << endl;
ndbout << page << endl;
abort();
}
} }
loop: loop:
int op; int op;
int rnd= rand() % 100; int rnd= rand() % 100;
for(op= 0; op<3; op++) for(op= 0; op<5; op++)
if(rnd < dist[op]) if(rnd < dist[op])
break; break;
@ -69,9 +98,73 @@ loop:
{ {
rec.data[i] = rand(); rec.data[i] = rand();
} }
ndbout << "Alloc " << rec.size << flush; ndbout << "Alloc hi: " << page.high_index << " (" <<
((rnd < 30) ? "any" :
(rnd < 60) ? "dir" :
(rnd < 80) ? "exp" : "fail") << ") ";
ndbout << rec.size << flush;
if (rnd < 30)
{
rec.idx= page.alloc_record(rec.size, &tmp, 0); rec.idx= page.alloc_record(rec.size, &tmp, 0);
ndbout << " -> " << rec.idx << endl; }
else if (rnd < 60)
{
// Alloc with id, from directory
Vector<Uint32> free;
for(Uint32 i = page.high_index - 1; i > 0; i--)
{
if (page.get_index_word(i) & page.FREE)
{
free.push_back(i);
if (free.size() > 100)
break;
}
}
if (free.size())
{
rec.idx = free[rand() % free.size()];
if (page.alloc_record(rec.idx, rec.size, &tmp) != rec.idx)
{
abort();
}
}
else
{
rec.idx = page.high_index;
if (page.alloc_record(rec.idx, rec.size, &tmp) != rec.idx)
{
if (rec.size + 1 != page.free_space)
abort();
delete [] rec.data;
ndbout_c(" FAIL");
break;
}
}
}
else if(rnd < 80)
{
// Alloc with id, outside of directory
rec.idx = page.high_index + (rand() % (page.free_space - rec.size));
if (page.alloc_record(rec.idx, rec.size, &tmp) != rec.idx)
{
abort();
}
}
else
{
rec.idx = page.high_index + (page.free_space - rec.size) + 1;
if (page.alloc_record(rec.idx, rec.size, &tmp) == rec.idx)
{
abort();
}
delete [] rec.data;
ndbout_c(" FAIL");
break;
}
Uint32 pos = page.get_ptr(rec.idx) - page.m_data;
ndbout << " -> " << rec.idx
<< " pos: " << pos << endl;
Uint32* ptr= page.get_ptr(rec.idx); Uint32* ptr= page.get_ptr(rec.idx);
memcpy(ptr, rec.data, 4*rec.size); memcpy(ptr, rec.data, 4*rec.size);
records[allocated++] = rec; records[allocated++] = rec;
@ -81,8 +174,10 @@ loop:
{ {
int no= rand() % allocated; int no= rand() % allocated;
Record rec= records[no]; Record rec= records[no];
ndbout << "Free no: " << no << " idx: " << rec.idx << endl; Uint32 pos = page.get_ptr(rec.idx) - page.m_data;
ndbout << "Free hi: " << page.high_index << " no: " << no << " idx: " << rec.idx << " pos: " << pos << endl;
Uint32* ptr= page.get_ptr(rec.idx); Uint32* ptr= page.get_ptr(rec.idx);
assert(page.get_entry_len(rec.idx) == rec.size);
cmp(ptr, rec.data, rec.size); cmp(ptr, rec.data, rec.size);
delete[] rec.data; delete[] rec.data;
page.free_record(rec.idx, 0); page.free_record(rec.idx, 0);
@ -98,8 +193,57 @@ loop:
page.reorg(&tmp); page.reorg(&tmp);
break; break;
case 3: case 3:
ndbout << "Expand" << endl; {
Uint32 free = page.free_space;
if (free <= 2)
{
goto shrink;
}
free /= 2;
int no = rand() % allocated;
Record rec= records[no];
ndbout << "Expand no: " << no << " idx: " << rec.idx
<< " add: " << free << " reorg: "
<< !page.is_space_behind_entry(rec.idx, free)
<< endl;
if (!page.is_space_behind_entry(rec.idx, free))
{
Uint32 buffer[8192];
Uint32 len = page.get_entry_len(rec.idx);
memcpy(buffer, page.get_ptr(rec.idx), 4*len);
page.set_entry_len(rec.idx, 0);
page.free_space += len;
page.reorg(&tmp);
memcpy(page.get_free_space_ptr(), buffer, 4*len);
page.set_entry_offset(rec.idx, page.insert_pos);
free += len;
records[no].size = 0;
}
page.grow_entry(rec.idx, free);
records[no].size += free;
Uint32 *ptr = page.get_ptr(rec.idx);
Uint32 *new_data = new Uint32[records[no].size];
for(Uint32 i= 0; i<records[no].size; i++)
{
ptr[i] = new_data[i] = rand();
}
delete []rec.data;
records[no].data = new_data;
break;
}
case 4:
{
shrink:
int no = rand() % allocated;
Record rec = records[no];
Uint32 sz = rec.size / 2 + 1;
ndbout << "Shrink no: " << no << " idx: " << rec.idx << " remove: "
<< (rec.size - sz) << endl;
page.shrink_entry(rec.idx, sz);
records[no].size = sz;
break;
}
} }
} }
@ -107,19 +251,27 @@ loop:
} }
int int
main(void) main(int argc, char **argv)
{ {
ndb_init(); ndb_init();
int t1[] = { 30, 90, 100 }; if (argc > 1)
int t2[] = { 45, 90, 100 }; {
int t3[] = { 60, 90, 100 }; time_t seed = time(0);
int t4[] = { 75, 90, 100 }; srand(seed);
fprintf(stderr, "srand(%d)\n", seed);
}
// alloc, free, reorg, grow, shrink
int t1[] = { 10, 60, 70, 85, 100 };
int t2[] = { 30, 60, 70, 85, 100 };
int t3[] = { 50, 60, 70, 85, 100 };
do_test(10000, t1); do_test(10000, t1);
do_test(10000, t2); do_test(10000, t2);
do_test(10000, t3); do_test(10000, t3);
do_test(10000, t4);
return 0;
} }
template class Vector<Record>; template class Vector<Record>;

View File

@ -18,6 +18,20 @@
#include "tuppage.hpp" #include "tuppage.hpp"
#include "Dbtup.hpp" #include "Dbtup.hpp"
/**
* Fix pages maintain a double linked list of free entries
*
* Var pages has a directory where each entry is
* [ C(1), F(1), L(15), P(15) ]
* C is chain bit, (is it a full tuple or just chain)
* F is free bit
* If true, L is prev free entry (in directory)
* P is next free entry (in directory)
* else
* L is len of entry
* P is pos of entry
*/
Uint32 Uint32
Tup_fixsize_page::alloc_record() Tup_fixsize_page::alloc_record()
{ {
@ -29,7 +43,7 @@ Tup_fixsize_page::alloc_record()
Uint32 next = m_data[page_idx] & 0xFFFF; Uint32 next = m_data[page_idx] & 0xFFFF;
assert(prev == 0xFFFF); assert(prev == 0xFFFF);
assert(m_data[page_idx + 1] == Dbtup::Tuple_header::FREE); assert(m_data[page_idx + 1] == FREE_RECORD);
m_data[page_idx + 1] = 0; m_data[page_idx + 1] = 0;
if (next != 0xFFFF) if (next != 0xFFFF)
@ -53,7 +67,7 @@ Uint32
Tup_fixsize_page::alloc_record(Uint32 page_idx) Tup_fixsize_page::alloc_record(Uint32 page_idx)
{ {
assert(page_idx + 1 < DATA_WORDS); assert(page_idx + 1 < DATA_WORDS);
if (likely(free_space && m_data[page_idx + 1] == Dbtup::Tuple_header::FREE)) if (likely(free_space && m_data[page_idx + 1] == FREE_RECORD))
{ {
Uint32 prev = m_data[page_idx] >> 16; Uint32 prev = m_data[page_idx] >> 16;
Uint32 next = m_data[page_idx] & 0xFFFF; Uint32 next = m_data[page_idx] & 0xFFFF;
@ -87,7 +101,7 @@ Tup_fixsize_page::free_record(Uint32 page_idx)
Uint32 next = next_free_index; Uint32 next = next_free_index;
assert(page_idx + 1 < DATA_WORDS); assert(page_idx + 1 < DATA_WORDS);
assert(m_data[page_idx + 1] != Dbtup::Tuple_header::FREE); assert(m_data[page_idx + 1] != FREE_RECORD);
if (next == 0xFFFF) if (next == 0xFFFF)
{ {
@ -100,12 +114,12 @@ Tup_fixsize_page::free_record(Uint32 page_idx)
Uint32 nextP = m_data[next]; Uint32 nextP = m_data[next];
assert((nextP >> 16) == 0xFFFF); assert((nextP >> 16) == 0xFFFF);
m_data[next] = (page_idx << 16) | (nextP & 0xFFFF); m_data[next] = (page_idx << 16) | (nextP & 0xFFFF);
assert(m_data[next + 1] == Dbtup::Tuple_header::FREE); assert(m_data[next + 1] == FREE_RECORD);
} }
next_free_index = page_idx; next_free_index = page_idx;
m_data[page_idx] = 0xFFFF0000 | next; m_data[page_idx] = 0xFFFF0000 | next;
m_data[page_idx + 1] = Dbtup::Tuple_header::FREE; m_data[page_idx + 1] = FREE_RECORD;
return ++free_space; return ++free_space;
} }
@ -116,10 +130,122 @@ Tup_varsize_page::init()
free_space= DATA_WORDS - 1; free_space= DATA_WORDS - 1;
high_index= 1; high_index= 1;
insert_pos= 0; insert_pos= 0;
next_free_index= 0xFFFF; next_free_index= END_OF_FREE_LIST;
m_page_header.m_page_type = File_formats::PT_Tup_varsize_page; m_page_header.m_page_type = File_formats::PT_Tup_varsize_page;
} }
Uint32
Tup_varsize_page::alloc_record(Uint32 page_idx, Uint32 alloc_size,
Tup_varsize_page* temp)
{
assert(page_idx); // 0 is not allowed
Uint32 free = free_space;
Uint32 largest_size= DATA_WORDS - (insert_pos + high_index);
Uint32 free_list = next_free_index;
if (page_idx < high_index)
{
Uint32 *ptr = get_index_ptr(page_idx);
Uint32 word = *ptr;
if (unlikely((free < alloc_size) || ! (word & FREE)))
{
return ~0;
}
if (alloc_size >= largest_size)
{
/*
We can't fit this segment between the insert position and the end of
the index entries. We will pack the page so that all free space
exists between the insert position and the end of the index entries.
*/
reorg(temp);
}
Uint32 next = (word & NEXT_MASK) >> NEXT_SHIFT;
Uint32 prev = (word & PREV_MASK) >> PREV_SHIFT;
if (next != END_OF_FREE_LIST)
{
Uint32 * next_ptr = get_index_ptr(next);
Uint32 next_word = * next_ptr;
* next_ptr = (next_word & ~PREV_MASK) | (prev << PREV_SHIFT);
}
if (prev != END_OF_FREE_LIST)
{
Uint32 * prev_ptr = get_index_ptr(prev);
Uint32 prev_word = * prev_ptr;
* prev_ptr = (prev_word & ~NEXT_MASK) | (next << NEXT_SHIFT);
}
else
{
assert(next_free_index == page_idx);
next_free_index = next;
}
* ptr = insert_pos + (alloc_size << LEN_SHIFT);
free -= alloc_size;
}
else
{
/**
* We need to expand directory
*/
Uint32 hi = high_index;
Uint32 expand = (page_idx + 1 - hi);
Uint32 size = alloc_size + expand;
if (unlikely(size > free))
{
return ~0;
}
if (size >= largest_size)
{
/*
We can't fit this segment between the insert position and the end of
the index entries. We will pack the page so that all free space
exists between the insert position and the end of the index entries.
*/
reorg(temp);
}
Uint32 *ptr = m_data + DATA_WORDS - hi;
if (page_idx == hi)
{
* ptr = insert_pos + (alloc_size << LEN_SHIFT);
}
else
{
if (free_list != END_OF_FREE_LIST)
{
Uint32 * prev_ptr = get_index_ptr(free_list);
Uint32 prev_word = * prev_ptr;
* prev_ptr = (prev_word & ~PREV_MASK) | (hi << PREV_SHIFT);
}
for (; hi < page_idx;)
{
* ptr-- = FREE | (free_list << NEXT_SHIFT) | ((hi+1) << PREV_SHIFT);
free_list = hi++;
}
* ptr++ = insert_pos + (alloc_size << LEN_SHIFT);
* ptr = ((* ptr) & ~PREV_MASK) | (END_OF_FREE_LIST << PREV_SHIFT);
next_free_index = hi - 1;
}
high_index = hi + 1;
free -= size;
}
free_space = free;
insert_pos += alloc_size;
return page_idx;
}
Uint32 Uint32
Tup_varsize_page::alloc_record(Uint32 alloc_size, Tup_varsize_page::alloc_record(Uint32 alloc_size,
Tup_varsize_page* temp, Uint32 chain) Tup_varsize_page* temp, Uint32 chain)
@ -138,7 +264,7 @@ Tup_varsize_page::alloc_record(Uint32 alloc_size,
assert(largest_size > alloc_size); assert(largest_size > alloc_size);
Uint32 page_idx; Uint32 page_idx;
if (next_free_index == 0xFFFF) { if (next_free_index == END_OF_FREE_LIST) {
/* /*
We are out of free index slots. We will extend the array of free We are out of free index slots. We will extend the array of free
slots slots
@ -148,12 +274,21 @@ Tup_varsize_page::alloc_record(Uint32 alloc_size,
} else { } else {
// Pick an empty slot among the index entries // Pick an empty slot among the index entries
page_idx= next_free_index; page_idx= next_free_index;
assert((get_index_word(page_idx) & 0xFFFF0000) == 0); assert((get_index_word(page_idx) & FREE) == FREE);
next_free_index= get_index_word(page_idx); assert(((get_index_word(page_idx) & PREV_MASK) >> PREV_SHIFT) ==
END_OF_FREE_LIST);
next_free_index= (get_index_word(page_idx) & NEXT_MASK) >> NEXT_SHIFT;
assert(next_free_index);
if (next_free_index != END_OF_FREE_LIST)
{
Uint32 *ptr = get_index_ptr(next_free_index);
Uint32 word = *ptr;
* ptr = (word & ~PREV_MASK) | (END_OF_FREE_LIST << PREV_SHIFT);
}
} }
assert(chain == 0 || chain == CHAIN); assert(chain == 0 || chain == CHAIN);
* get_index_ptr(page_idx) = insert_pos + ((chain + alloc_size) << 16); * get_index_ptr(page_idx) = insert_pos + chain + (alloc_size << LEN_SHIFT);
insert_pos += alloc_size; insert_pos += alloc_size;
free_space -= alloc_size; free_space -= alloc_size;
@ -167,10 +302,10 @@ Tup_varsize_page::free_record(Uint32 page_idx, Uint32 chain)
//ndbout_c("%p->free_record(%d%s)", this, page_idx, (chain ? " CHAIN": "")); //ndbout_c("%p->free_record(%d%s)", this, page_idx, (chain ? " CHAIN": ""));
Uint32 *index_ptr= get_index_ptr(page_idx); Uint32 *index_ptr= get_index_ptr(page_idx);
Uint32 index_word= * index_ptr; Uint32 index_word= * index_ptr;
Uint32 entry_pos= index_word & 0xFFFF; Uint32 entry_pos= (index_word & POS_MASK) >> POS_SHIFT;
Uint32 entry_len= (index_word >> 16) & ~CHAIN; Uint32 entry_len= (index_word & LEN_MASK) >> LEN_SHIFT;
assert(chain == 0 || chain == CHAIN); assert(chain == 0 || chain == CHAIN);
assert(!(((index_word >> 16) ^ chain) & 0x8000)); assert((index_word & CHAIN) == chain);
#ifdef VM_TRACE #ifdef VM_TRACE
memset(m_data + entry_pos, 0xF2, 4*entry_len); memset(m_data + entry_pos, 0xF2, 4*entry_len);
#endif #endif
@ -183,8 +318,16 @@ Tup_varsize_page::free_record(Uint32 page_idx, Uint32 chain)
*/ */
rebuild_index(index_ptr); rebuild_index(index_ptr);
} else { } else {
* index_ptr= next_free_index; if (next_free_index != END_OF_FREE_LIST)
{
Uint32 *ptr = get_index_ptr(next_free_index);
Uint32 word = *ptr;
assert(((word & PREV_MASK) >> PREV_SHIFT) == END_OF_FREE_LIST);
* ptr = (word & ~PREV_MASK) | (page_idx << PREV_SHIFT);
}
* index_ptr= FREE | next_free_index | (END_OF_FREE_LIST << PREV_SHIFT);
next_free_index= page_idx; next_free_index= page_idx;
assert(next_free_index);
} }
free_space+= entry_len; free_space+= entry_len;
@ -204,7 +347,7 @@ Tup_varsize_page::rebuild_index(Uint32* index_ptr)
* Scan until you find first non empty index pos * Scan until you find first non empty index pos
*/ */
for(index_ptr++; index_ptr < end; index_ptr++) for(index_ptr++; index_ptr < end; index_ptr++)
if((* index_ptr >> 16) == 0) if((* index_ptr) & FREE)
empty++; empty++;
else else
break; break;
@ -214,23 +357,30 @@ Tup_varsize_page::rebuild_index(Uint32* index_ptr)
// Totally free page // Totally free page
high_index = 1; high_index = 1;
free_space += empty; free_space += empty;
next_free_index= 0xFFFF; next_free_index = END_OF_FREE_LIST;
return; return;
} }
Uint32 next= 0xFFFF; Uint32 next= END_OF_FREE_LIST;
high_index -= empty; Uint32 dummy;
Uint32 *prev_ptr = &dummy;
for(index_ptr++; index_ptr < end; index_ptr++) for(index_ptr++; index_ptr < end; index_ptr++)
{ {
if((* index_ptr >> 16) == 0) if ((* index_ptr) & FREE)
{ {
* index_ptr= next; * index_ptr= FREE | next;
next= (end - index_ptr); next= (end - index_ptr);
* prev_ptr |= (next << PREV_SHIFT);
prev_ptr = index_ptr;
} }
} }
* prev_ptr |= (END_OF_FREE_LIST << PREV_SHIFT);
high_index -= empty;
free_space += empty; free_space += empty;
next_free_index= next; next_free_index= next;
assert(next_free_index);
} }
void void
@ -247,16 +397,17 @@ Tup_varsize_page::reorg(Tup_varsize_page* copy_page)
for (; index_ptr < end_of_page; index_ptr++) for (; index_ptr < end_of_page; index_ptr++)
{ {
Uint32 index_word= * index_ptr; Uint32 index_word= * index_ptr;
Uint32 entry_len= (index_word >> 16) & ~CHAIN; Uint32 entry_len= (index_word & LEN_MASK) >> LEN_SHIFT;
if (entry_len != 0) { if (!(index_word & FREE) && entry_len)
{
/* /*
We found an index item that needs to be packed. We found an index item that needs to be packed.
We will update the index entry and copy the data to the page. We will update the index entry and copy the data to the page.
*/ */
Uint32 entry_pos= index_word & 0xffff; Uint32 entry_pos= (index_word & POS_MASK) >> POS_SHIFT;
assert(entry_pos + entry_len <= old_insert_pos); assert(entry_pos + entry_len <= old_insert_pos);
assert(new_insert_pos + entry_len <= old_insert_pos); assert(new_insert_pos + entry_len <= old_insert_pos);
* index_ptr= new_insert_pos + (index_word & 0xFFFF0000); * index_ptr= (new_insert_pos << POS_SHIFT) + (index_word & ~POS_MASK);
memcpy(m_data+new_insert_pos, copy_page->m_data+entry_pos, 4*entry_len); memcpy(m_data+new_insert_pos, copy_page->m_data+entry_pos, 4*entry_len);
new_insert_pos += entry_len; new_insert_pos += entry_len;
@ -278,10 +429,10 @@ operator<< (NdbOut& out, const Tup_varsize_page& page)
for(Uint32 i = 1; i<page.high_index; i++, index_ptr--) for(Uint32 i = 1; i<page.high_index; i++, index_ptr--)
{ {
out << " [ " << i; out << " [ " << i;
if(*index_ptr >> 16) if(! (*index_ptr & page.FREE))
out << " pos: " << ((*index_ptr) & 0xFFFF) out << " pos: " << ((* index_ptr & page.POS_MASK) >> page.POS_SHIFT)
<< " len: " << ((*index_ptr >> 16) & ~page.CHAIN) << " len: " << ((* index_ptr & page.LEN_MASK) >> page.LEN_SHIFT)
<< (((* index_ptr >> 16) & page.CHAIN) ? " CHAIN " : " ") << ((* index_ptr & page.CHAIN) ? " CHAIN " : " ")
<< "]" << flush; << "]" << flush;
else else
out << " FREE ]" << flush; out << " FREE ]" << flush;
@ -289,10 +440,10 @@ operator<< (NdbOut& out, const Tup_varsize_page& page)
out << " free list: " << flush; out << " free list: " << flush;
Uint32 next= page.next_free_index; Uint32 next= page.next_free_index;
while(next != 0xFFFF) while(next != page.END_OF_FREE_LIST)
{ {
out << next << " " << flush; out << next << " " << flush;
next= * (page.m_data+page.DATA_WORDS-next); next= ((* (page.m_data+page.DATA_WORDS-next)) & page.NEXT_MASK) >> page.NEXT_SHIFT;
} }
out << "]"; out << "]";
return out; return out;

View File

@ -81,6 +81,7 @@ struct Tup_fixsize_page
Uint32 m_extent_info_ptr; Uint32 m_extent_info_ptr;
Uint32 unused_ph[9]; Uint32 unused_ph[9];
STATIC_CONST( FREE_RECORD = ~(Uint32)0 );
STATIC_CONST( DATA_WORDS = File_formats::NDB_PAGE_SIZE_WORDS - 32 ); STATIC_CONST( DATA_WORDS = File_formats::NDB_PAGE_SIZE_WORDS - 32 );
Uint32 m_data[DATA_WORDS]; Uint32 m_data[DATA_WORDS];
@ -127,7 +128,18 @@ struct Tup_varsize_page
Uint32 unused_ph[7]; Uint32 unused_ph[7];
STATIC_CONST( DATA_WORDS = File_formats::NDB_PAGE_SIZE_WORDS - 32 ); STATIC_CONST( DATA_WORDS = File_formats::NDB_PAGE_SIZE_WORDS - 32 );
STATIC_CONST( CHAIN = 0x8000 ); STATIC_CONST( CHAIN = 0x80000000 );
STATIC_CONST( FREE = 0x40000000 );
STATIC_CONST( LEN_MASK = 0x3FFF8000 );
STATIC_CONST( POS_MASK = 0x00007FFF );
STATIC_CONST( LEN_SHIFT = 15 );
STATIC_CONST( POS_SHIFT = 0 );
STATIC_CONST( END_OF_FREE_LIST = POS_MASK );
STATIC_CONST( NEXT_MASK = POS_MASK );
STATIC_CONST( NEXT_SHIFT = POS_SHIFT );
STATIC_CONST( PREV_MASK = LEN_MASK );
STATIC_CONST( PREV_SHIFT = LEN_SHIFT );
Uint32 m_data[DATA_WORDS]; Uint32 m_data[DATA_WORDS];
@ -157,6 +169,12 @@ struct Tup_varsize_page
*/ */
Uint32 alloc_record(Uint32 size, Tup_varsize_page* temp, Uint32 chain); Uint32 alloc_record(Uint32 size, Tup_varsize_page* temp, Uint32 chain);
/**
* Alloc page_idx from page, return page_idx
* temp is used when having to reorg page before allocating
*/
Uint32 alloc_record(Uint32 page_idx, Uint32 size, Tup_varsize_page* temp);
/** /**
* Free record from page * Free record from page
*/ */
@ -170,8 +188,8 @@ struct Tup_varsize_page
*/ */
bool is_space_behind_entry(Uint32 page_index, Uint32 growth_len) const { bool is_space_behind_entry(Uint32 page_index, Uint32 growth_len) const {
Uint32 idx= get_index_word(page_index); Uint32 idx= get_index_word(page_index);
Uint32 pos= idx & 0xFFFF; Uint32 pos= (idx & POS_MASK) >> POS_SHIFT;
Uint32 len= (idx >> 16) & ~CHAIN; Uint32 len= (idx & LEN_MASK) >> LEN_SHIFT;
if ((pos + len == insert_pos) && if ((pos + len == insert_pos) &&
(insert_pos + growth_len < DATA_WORDS - high_index)) (insert_pos + growth_len < DATA_WORDS - high_index))
return true; return true;
@ -183,9 +201,11 @@ struct Tup_varsize_page
Uint32 *pos= get_index_ptr(page_index); Uint32 *pos= get_index_ptr(page_index);
Uint32 idx= *pos; Uint32 idx= *pos;
Uint32 size= (idx >> 16) + growth_len; assert(! (idx & FREE));
*pos= (idx & 0xFFFF) + (size << 16); assert((((idx & POS_MASK) >> POS_SHIFT) + ((idx & LEN_MASK) >> LEN_SHIFT))
assert((idx & 0xFFFF) + ((idx >> 16) & ~CHAIN) == insert_pos); == insert_pos);
* pos= idx + (growth_len << LEN_SHIFT);
insert_pos+= growth_len; insert_pos+= growth_len;
free_space-= growth_len; free_space-= growth_len;
} }
@ -193,35 +213,42 @@ struct Tup_varsize_page
void shrink_entry(Uint32 page_index, Uint32 new_size){ void shrink_entry(Uint32 page_index, Uint32 new_size){
Uint32 *pos= get_index_ptr(page_index); Uint32 *pos= get_index_ptr(page_index);
Uint32 idx= *pos; Uint32 idx= *pos;
*pos= (idx & (CHAIN << 16 | 0xFFFF)) + (new_size << 16); Uint32 old_pos = (idx & POS_MASK) >> POS_SHIFT;
Uint32 old_size= (idx >> 16) & ~CHAIN; Uint32 old_size = (idx & LEN_MASK) >> LEN_SHIFT;
assert( ! (idx & FREE));
assert(old_size >= new_size); assert(old_size >= new_size);
* pos= (idx & ~LEN_MASK) + (new_size << LEN_SHIFT);
Uint32 shrink = old_size - new_size; Uint32 shrink = old_size - new_size;
#ifdef VM_TRACE #ifdef VM_TRACE
memset(m_data + (idx & 0xFFFF) + new_size, 0xF1, 4 * shrink); memset(m_data + old_pos + new_size, 0xF1, 4 * shrink);
#endif #endif
free_space+= shrink; free_space+= shrink;
if(insert_pos == ((idx & 0xFFFF) + old_size)) if(insert_pos == (old_pos + old_size))
insert_pos -= shrink; insert_pos -= shrink;
} }
Uint32* get_ptr(Uint32 page_idx) { Uint32* get_ptr(Uint32 page_idx) {
return m_data + (get_index_word(page_idx) & 0xFFFF); return m_data + ((get_index_word(page_idx) & POS_MASK) >> POS_SHIFT);
} }
void set_entry_offset(Uint32 page_idx, Uint32 offset){ void set_entry_offset(Uint32 page_idx, Uint32 offset){
Uint32 *pos= get_index_ptr(page_idx); Uint32 *pos= get_index_ptr(page_idx);
*pos = (* pos & 0xFFFF0000) + offset; * pos = (* pos & ~POS_MASK) + (offset << POS_SHIFT);
}
Uint32 get_entry_len(Uint32 page_idx) const {
return get_index_word(page_idx) >> 16;
} }
void set_entry_len(Uint32 page_idx, Uint32 len) { void set_entry_len(Uint32 page_idx, Uint32 len) {
Uint32 *pos= get_index_ptr(page_idx); Uint32 *pos= get_index_ptr(page_idx);
*pos = (len << 16) + (*pos & (CHAIN << 16 | 0xFFFF)); * pos = (*pos & ~LEN_MASK) + (len << LEN_SHIFT);
}
Uint32 get_entry_len(Uint32 page_idx) const {
return (get_index_word(page_idx) & LEN_MASK) >> LEN_SHIFT;
}
Uint32 get_entry_chain(Uint32 page_idx) const {
return get_index_word(page_idx) & CHAIN;
} }
}; };

View File

@ -26,6 +26,7 @@
#include <signaldata/LCP.hpp> #include <signaldata/LCP.hpp>
#include <signaldata/SumaImpl.hpp> #include <signaldata/SumaImpl.hpp>
#include <signaldata/LgmanContinueB.hpp> #include <signaldata/LgmanContinueB.hpp>
#include <signaldata/GetTabInfo.hpp>
#include "ndbfs/Ndbfs.hpp" #include "ndbfs/Ndbfs.hpp"
#include "dbtup/Dbtup.hpp" #include "dbtup/Dbtup.hpp"
@ -87,6 +88,8 @@ Lgman::Lgman(const Configuration & conf) :
addRecSignal(GSN_END_LCP_CONF, &Lgman::execEND_LCP_CONF); addRecSignal(GSN_END_LCP_CONF, &Lgman::execEND_LCP_CONF);
addRecSignal(GSN_GET_TABINFOREQ, &Lgman::execGET_TABINFOREQ);
m_last_lsn = 0; m_last_lsn = 0;
m_logfile_group_pool.setSize(10); m_logfile_group_pool.setSize(10);
m_logfile_group_hash.setSize(10); m_logfile_group_hash.setSize(10);
@ -701,6 +704,7 @@ Lgman::create_file_commit(Signal* signal,
ptr.p->m_state = Undofile::FS_SORTING; ptr.p->m_state = Undofile::FS_SORTING;
} }
ptr.p->m_online.m_lsn = 0;
ptr.p->m_online.m_outstanding = 0; ptr.p->m_online.m_outstanding = 0;
Uint64 add= ptr.p->m_file_size - 1; Uint64 add= ptr.p->m_file_size - 1;
@ -1648,7 +1652,7 @@ Lgman::execLCP_FRAG_ORD(Signal* signal)
sendSignal(reference(), GSN_CONTINUEB, signal, 2, JBB); sendSignal(reference(), GSN_CONTINUEB, signal, 2, JBB);
} }
if(!ptr.isNull()) if(!ptr.isNull() && ptr.p->m_last_lsn)
{ {
Uint32 undo[3]; Uint32 undo[3];
undo[0] = lcp_id; undo[0] = lcp_id;
@ -1685,6 +1689,8 @@ Lgman::execLCP_FRAG_ORD(Signal* signal)
} }
while(!ptr.isNull()) while(!ptr.isNull())
{
if (ptr.p->m_last_lsn)
{ {
/** /**
* First LCP_FRAGORD for each LCP, sets tail pos * First LCP_FRAGORD for each LCP, sets tail pos
@ -1703,7 +1709,7 @@ Lgman::execLCP_FRAG_ORD(Signal* signal)
ptr.p->m_tail_pos[1].m_ptr_i, ptr.p->m_tail_pos[1].m_idx, ptr.p->m_tail_pos[1].m_ptr_i, ptr.p->m_tail_pos[1].m_idx,
ptr.p->m_tail_pos[2].m_ptr_i, ptr.p->m_tail_pos[2].m_idx, ptr.p->m_tail_pos[2].m_ptr_i, ptr.p->m_tail_pos[2].m_idx,
(ptr.p->m_free_file_words / File_formats::UNDO_PAGE_WORDS)); (ptr.p->m_free_file_words / File_formats::UNDO_PAGE_WORDS));
}
m_logfile_group_list.next(ptr); m_logfile_group_list.next(ptr);
} }
@ -1761,13 +1767,15 @@ Lgman::endlcp_callback(Signal* signal, Uint32 ptr, Uint32 res)
void void
Lgman::cut_log_tail(Signal* signal, Ptr<Logfile_group> ptr) Lgman::cut_log_tail(Signal* signal, Ptr<Logfile_group> ptr)
{ {
bool done= true;
if (likely(ptr.p->m_last_lsn))
{
Buffer_idx tmp= ptr.p->m_tail_pos[0]; Buffer_idx tmp= ptr.p->m_tail_pos[0];
Buffer_idx tail= ptr.p->m_file_pos[TAIL]; Buffer_idx tail= ptr.p->m_file_pos[TAIL];
Ptr<Undofile> filePtr; Ptr<Undofile> filePtr;
m_file_pool.getPtr(filePtr, tail.m_ptr_i); m_file_pool.getPtr(filePtr, tail.m_ptr_i);
bool done= true;
if(!(tmp == tail)) if(!(tmp == tail))
{ {
Uint32 free; Uint32 free;
@ -1802,6 +1810,7 @@ Lgman::cut_log_tail(Signal* signal, Ptr<Logfile_group> ptr)
} }
validate_logfile_group(ptr, "cut log"); validate_logfile_group(ptr, "cut log");
}
if (done) if (done)
{ {
@ -2946,3 +2955,71 @@ Lgman::validate_logfile_group(Ptr<Logfile_group> ptr, const char * heading)
} }
} }
#endif #endif
void Lgman::execGET_TABINFOREQ(Signal* signal)
{
jamEntry();
if(!assembleFragments(signal))
{
return;
}
GetTabInfoReq * const req = (GetTabInfoReq *)&signal->theData[0];
const Uint32 reqType = req->requestType & (~GetTabInfoReq::LongSignalConf);
BlockReference retRef= req->senderRef;
Uint32 senderData= req->senderData;
Uint32 tableId= req->tableId;
if(reqType == GetTabInfoReq::RequestByName){
jam();
if(signal->getNoOfSections())
releaseSections(signal);
sendGET_TABINFOREF(signal, req, GetTabInfoRef::NoFetchByName);
return;
}
Logfile_group key;
key.m_logfile_group_id= tableId;
Ptr<Logfile_group> ptr;
m_logfile_group_hash.find(ptr, key);
if(ptr.p->m_logfile_group_id != tableId)
{
jam();
if(signal->getNoOfSections())
releaseSections(signal);
sendGET_TABINFOREF(signal, req, GetTabInfoRef::InvalidTableId);
return;
}
GetTabInfoConf *conf = (GetTabInfoConf *)&signal->theData[0];
conf->senderData= senderData;
conf->tableId= tableId;
conf->freeWordsHi= ptr.p->m_free_file_words >> 32;
conf->freeWordsLo= ptr.p->m_free_file_words & 0xFFFFFFFF;
conf->tableType= DictTabInfo::LogfileGroup;
conf->senderRef= reference();
sendSignal(retRef, GSN_GET_TABINFO_CONF, signal,
GetTabInfoConf::SignalLength, JBB);
}
void Lgman::sendGET_TABINFOREF(Signal* signal,
GetTabInfoReq * req,
GetTabInfoRef::ErrorCode errorCode)
{
jamEntry();
GetTabInfoRef * const ref = (GetTabInfoRef *)&signal->theData[0];
/**
* The format of GetTabInfo Req/Ref is the same
*/
BlockReference retRef = req->senderRef;
ref->errorCode = errorCode;
sendSignal(retRef, GSN_GET_TABINFOREF, signal, signal->length(), JBB);
}

View File

@ -26,6 +26,7 @@
#include <DLHashTable.hpp> #include <DLHashTable.hpp>
#include <NodeBitmask.hpp> #include <NodeBitmask.hpp>
#include "diskpage.hpp" #include "diskpage.hpp"
#include <signaldata/GetTabInfo.hpp>
class Lgman : public SimulatedBlock class Lgman : public SimulatedBlock
{ {
@ -66,6 +67,13 @@ protected:
void execSTART_RECREQ(Signal*); void execSTART_RECREQ(Signal*);
void execEND_LCP_CONF(Signal*); void execEND_LCP_CONF(Signal*);
void execGET_TABINFOREQ(Signal*);
void sendGET_TABINFOREF(Signal* signal,
GetTabInfoReq * req,
GetTabInfoRef::ErrorCode errorCode);
public: public:
struct Log_waiter struct Log_waiter
{ {

View File

@ -341,11 +341,13 @@ void AsyncFile::openReq(Request* request)
#endif #endif
} }
#ifndef NDB_NO_O_DIRECT /* to allow tmpfs */
#ifdef O_DIRECT #ifdef O_DIRECT
if (flags & FsOpenReq::OM_DIRECT) if (flags & FsOpenReq::OM_DIRECT)
{ {
new_flags |= O_DIRECT; new_flags |= O_DIRECT;
} }
#endif
#endif #endif
switch(flags & 0x3){ switch(flags & 0x3){

View File

@ -1359,8 +1359,8 @@ void
Pgman::fsreadreq(Signal* signal, Ptr<Page_entry> ptr) Pgman::fsreadreq(Signal* signal, Ptr<Page_entry> ptr)
{ {
File_map::ConstDataBufferIterator it; File_map::ConstDataBufferIterator it;
m_file_map.first(it); bool ret = m_file_map.first(it) && m_file_map.next(it, ptr.p->m_file_no);
m_file_map.next(it, ptr.p->m_file_no); ndbrequire(ret);
Uint32 fd = * it.data; Uint32 fd = * it.data;
ndbrequire(ptr.p->m_page_no > 0); ndbrequire(ptr.p->m_page_no > 0);
@ -1479,11 +1479,6 @@ Pgman::get_page(Signal* signal, Ptr<Page_entry> ptr, Page_request page_req)
{ {
busy_count = true; busy_count = true;
state |= Page_entry::BUSY; state |= Page_entry::BUSY;
/*
* Consider commit to be correlated. Otherwise pk op + commit makes
* the page hot. XXX move to TUP which knows better.
*/
req_flags |= Page_request::CORR_REQ;
} }
else if ((req_flags & Page_request::OP_MASK) != ZREAD) else if ((req_flags & Page_request::OP_MASK) != ZREAD)
{ {
@ -2196,11 +2191,14 @@ Pgman::execDUMP_STATE_ORD(Signal* signal)
} }
} }
if (signal->theData[0] == 11003) if (signal->theData[0] == 11003)
{ {
#ifdef VM_TRACE #ifdef VM_TRACE
verify_page_lists(); verify_page_lists();
dump_page_lists(); dump_page_lists();
#else
ndbout << "Only in VM_TRACE builds" << endl;
#endif #endif
} }
} }

View File

@ -518,6 +518,7 @@ public:
,DIRTY_REQ = Pgman::Page_request::DIRTY_REQ ,DIRTY_REQ = Pgman::Page_request::DIRTY_REQ
,NO_HOOK = Pgman::Page_request::NO_HOOK ,NO_HOOK = Pgman::Page_request::NO_HOOK
,UNLOCK_PAGE = Pgman::Page_request::UNLOCK_PAGE ,UNLOCK_PAGE = Pgman::Page_request::UNLOCK_PAGE
,CORR_REQ = Pgman::Page_request::CORR_REQ
}; };
/** /**

View File

@ -817,7 +817,7 @@ Restore::parse_table_description(Signal* signal, FilePtr file_ptr,
c.m_flags |= (tmp.AttributeStorageType == NDB_STORAGETYPE_DISK ? c.m_flags |= (tmp.AttributeStorageType == NDB_STORAGETYPE_DISK ?
Column::COL_DISK : 0); Column::COL_DISK : 0);
if(lcp && c.m_flags & Column::COL_DISK) if(lcp && (c.m_flags & Column::COL_DISK))
{ {
/** /**
* Restore does not currently handle disk attributes * Restore does not currently handle disk attributes
@ -829,7 +829,6 @@ Restore::parse_table_description(Signal* signal, FilePtr file_ptr,
if(!tmp.AttributeNullableFlag && !varsize) if(!tmp.AttributeNullableFlag && !varsize)
{ {
c.m_nulloffset = 0;
if(!columns.append(_align, sizeof(Column)/sizeof(Uint32))) if(!columns.append(_align, sizeof(Column)/sizeof(Uint32)))
{ {
parse_error(signal, file_ptr, __LINE__, i); parse_error(signal, file_ptr, __LINE__, i);
@ -838,32 +837,22 @@ Restore::parse_table_description(Signal* signal, FilePtr file_ptr,
} }
else if (true) // null mask dropped in 5.1 else if (true) // null mask dropped in 5.1
{ {
c.m_nulloffset = (tmp.AttributeNullableFlag != 0); c.m_flags |= (varsize ? Column::COL_VAR : 0);
if (varsize) c.m_flags |= (tmp.AttributeNullableFlag ? Column::COL_NULL : 0);
c.m_flags |= Column::COL_VAR;
if(!columns.append(_align, sizeof(Column)/sizeof(Uint32))) if(!columns.append(_align, sizeof(Column)/sizeof(Uint32)))
{ {
parse_error(signal, file_ptr, __LINE__, i); parse_error(signal, file_ptr, __LINE__, i);
return; return;
} }
} }
else
{
c.m_nulloffset = 1 + null_offset++;
c.m_flags |= Column::COL_VAR;
if(!variable.append(_align, sizeof(Column)/sizeof(Uint32)))
{
parse_error(signal, file_ptr, __LINE__, i);
return;
}
}
} }
if(lcp && disk) if(lcp)
{
if (disk)
{ {
c.m_id = AttributeHeader::DISK_REF; c.m_id = AttributeHeader::DISK_REF;
c.m_size = 2; c.m_size = 2;
c.m_nulloffset = 0;
c.m_flags = 0; c.m_flags = 0;
if(!columns.append(_align, sizeof(Column)/sizeof(Uint32))) if(!columns.append(_align, sizeof(Column)/sizeof(Uint32)))
{ {
@ -872,19 +861,31 @@ Restore::parse_table_description(Signal* signal, FilePtr file_ptr,
} }
} }
file_ptr.p->m_table_version = tmpTab.TableVersion;
file_ptr.p->m_null_bitmask_size = (null_offset + 31)/32;
#if 0
List::Iterator cols;
for(variable.first(cols); !cols.isNull(); variable.next(cols))
{ {
if(!columns.append(cols.data, 1)) c.m_id = AttributeHeader::ROWID;
c.m_size = 2;
c.m_flags = 0;
if(!columns.append(_align, sizeof(Column)/sizeof(Uint32)))
{ {
parse_error(signal, file_ptr, __LINE__, 0); parse_error(signal, file_ptr, __LINE__, 0);
return;
} }
} }
return ;
#endif if (tmpTab.RowGCIFlag)
{
c.m_id = AttributeHeader::ROW_GCI;
c.m_size = 2;
c.m_flags = 0;
if(!columns.append(_align, sizeof(Column)/sizeof(Uint32)))
{
parse_error(signal, file_ptr, __LINE__, 0);
return;
}
}
}
file_ptr.p->m_table_version = tmpTab.TableVersion;
} }
void void
@ -927,11 +928,8 @@ Restore::parse_record(Signal* signal, FilePtr file_ptr,
Uint32 * const key_start = signal->getDataPtrSend()+24; Uint32 * const key_start = signal->getDataPtrSend()+24;
Uint32 * const attr_start = key_start + MAX_KEY_SIZE_IN_WORDS; Uint32 * const attr_start = key_start + MAX_KEY_SIZE_IN_WORDS;
Uint32 nulls= file_ptr.p->m_null_bitmask_size; data += 1;
const Uint32 *null_mask= data+1;
data += (1+nulls);
const Uint32* const dataStart = data; const Uint32* const dataStart = data;
//if (file_ptr.p->m_table_id >= 2) { for (uint ii = 0; ii+1<len; ii++) ndbout << hex << dataStart[ii]; ndbout << endl; }
Uint32 *keyData = key_start; Uint32 *keyData = key_start;
Uint32 *attrData = attr_start; Uint32 *attrData = attr_start;
@ -939,19 +937,36 @@ Restore::parse_record(Signal* signal, FilePtr file_ptr,
Column c; Column c;
Uint32 _align[1]; Uint32 _align[1];
}; };
bool disk= false; bool disk = false;
bool rowid = false;
bool gci = false;
//if (file_ptr.p->m_table_id >= 2) { ndbout << "*** "; columns.first(it); while (!it.isNull()) { _align[0] = *it.data; columns.next(it); _align[1] = *it.data; columns.next(it); ndbout << c << " "; } ndbout << endl; } Uint64 gci_val;
Local_key rowid_val;
Uint32 column_no = 0;
columns.first(it); columns.first(it);
while(!it.isNull()) while(!it.isNull())
{ {
_align[0] = *it.data; ndbrequire(columns.next(it)); _align[0] = *it.data; ndbrequire(columns.next(it));
_align[1] = *it.data; columns.next(it); _align[1] = *it.data; columns.next(it);
if (! (c.m_flags & Column::COL_VAR) && if (c.m_id == AttributeHeader::ROWID)
! c.m_nulloffset) {
rowid_val.m_page_no = data[0];
rowid_val.m_page_idx = data[1];
data += 2;
rowid = true;
continue;
}
if (c.m_id == AttributeHeader::ROW_GCI)
{
memcpy(&gci_val, data, 8);
data += 2;
gci = true;
continue;
}
if (! (c.m_flags & (Column::COL_VAR | Column::COL_NULL)))
{ {
ndbrequire(data < dataStart + len); ndbrequire(data < dataStart + len);
@ -965,11 +980,8 @@ Restore::parse_record(Signal* signal, FilePtr file_ptr,
memcpy(attrData, data, 4*c.m_size); memcpy(attrData, data, 4*c.m_size);
attrData += c.m_size; attrData += c.m_size;
data += c.m_size; data += c.m_size;
//if (file_ptr.p->m_table_id >= 2) ndbout << "1: " << c.m_id << " " << c.m_size << " col=" << column_no << endl;
} }
column_no++;
if(c.m_flags & Column::COL_DISK) if(c.m_flags & Column::COL_DISK)
disk= true; disk= true;
} }
@ -985,10 +997,9 @@ Restore::parse_record(Signal* signal, FilePtr file_ptr,
_align[1] = *it.data; _align[1] = *it.data;
Uint32 sz32 = (sz + 3) >> 2; Uint32 sz32 = (sz + 3) >> 2;
ndbassert(c.m_flags & (Column::COL_VAR | Column::COL_NULL));
if(c.m_flags & Column::COL_KEY) if(c.m_flags & Column::COL_KEY)
{ {
assert(! c.m_nulloffset && c.m_flags & Column::COL_VAR);
memcpy(keyData, data, 4 * sz32); memcpy(keyData, data, 4 * sz32);
keyData += sz32; keyData += sz32;
} }
@ -998,13 +1009,12 @@ Restore::parse_record(Signal* signal, FilePtr file_ptr,
attrData += sz32; attrData += sz32;
data += sz32; data += sz32;
//if (file_ptr.p->m_table_id >= 2) ndbout << "2: " << c.m_id << " " << sz << endl;
} }
ndbrequire(data == dataStart + len - 1); ndbrequire(data == dataStart + len - 1);
ndbrequire(disk == false); // Not supported... ndbrequire(disk == false); // Not supported...
ndbrequire(rowid == true);
Uint32 keyLen = keyData - key_start; Uint32 keyLen = keyData - key_start;
Uint32 attrLen = attrData - attr_start; Uint32 attrLen = attrData - attr_start;
LqhKeyReq * req = (LqhKeyReq *)signal->getDataPtrSend(); LqhKeyReq * req = (LqhKeyReq *)signal->getDataPtrSend();
@ -1029,7 +1039,6 @@ Restore::parse_record(Signal* signal, FilePtr file_ptr,
tmp= 0; tmp= 0;
LqhKeyReq::setKeyLen(tmp, keyLen); LqhKeyReq::setKeyLen(tmp, keyLen);
LqhKeyReq::setLastReplicaNo(tmp, 0); LqhKeyReq::setLastReplicaNo(tmp, 0);
LqhKeyReq::setLockType(tmp, ZINSERT);
/* ---------------------------------------------------------------------- */ /* ---------------------------------------------------------------------- */
// Indicate Application Reference is present in bit 15 // Indicate Application Reference is present in bit 15
/* ---------------------------------------------------------------------- */ /* ---------------------------------------------------------------------- */
@ -1040,7 +1049,8 @@ Restore::parse_record(Signal* signal, FilePtr file_ptr,
LqhKeyReq::setSameClientAndTcFlag(tmp, 0); LqhKeyReq::setSameClientAndTcFlag(tmp, 0);
LqhKeyReq::setAIInLqhKeyReq(tmp, 0); LqhKeyReq::setAIInLqhKeyReq(tmp, 0);
LqhKeyReq::setNoDiskFlag(tmp, disk ? 0 : 1); LqhKeyReq::setNoDiskFlag(tmp, disk ? 0 : 1);
//LqhKeyReq::setExecuteDirectFlag(tmp, 1); LqhKeyReq::setRowidFlag(tmp, 1);
LqhKeyReq::setGCIFlag(tmp, gci);
req->clientConnectPtr = file_ptr.i; req->clientConnectPtr = file_ptr.i;
req->hashValue = hashValue; req->hashValue = hashValue;
req->requestInfo = tmp; req->requestInfo = tmp;
@ -1053,9 +1063,14 @@ Restore::parse_record(Signal* signal, FilePtr file_ptr,
req->transId2 = 0; req->transId2 = 0;
req->scanInfo = 0; req->scanInfo = 0;
memcpy(req->variableData, key_start, 16); memcpy(req->variableData, key_start, 16);
Uint32 pos = keyLen > 4 ? 4 : keyLen;
req->variableData[pos++] = rowid_val.m_page_no;
req->variableData[pos++] = rowid_val.m_page_idx;
if (gci)
req->variableData[pos++] = (Uint32)gci_val;
file_ptr.p->m_outstanding_operations++; file_ptr.p->m_outstanding_operations++;
EXECUTE_DIRECT(DBLQH, GSN_LQHKEYREQ, signal, 11+(keyLen > 4 ? 4 : keyLen)); EXECUTE_DIRECT(DBLQH, GSN_LQHKEYREQ, signal,
LqhKeyReq::FixedSignalLength+pos);
if(keyLen > 4) if(keyLen > 4)
{ {
@ -1105,10 +1120,13 @@ Restore::reorder_key(const KeyDescriptor* desc,
memcpy(dst, var, 4 * sz); memcpy(dst, var, 4 * sz);
var += sz; var += sz;
break; break;
default:
ndbrequire(false);
sz = 0;
} }
dst += sz; dst += sz;
} }
assert((dst - Tmp) == len); ndbassert((dst - Tmp) == len);
memcpy(data, Tmp, 4*len); memcpy(data, Tmp, 4*len);
} }
@ -1201,9 +1219,9 @@ operator << (NdbOut& ndbout, const Restore::Column& col)
{ {
ndbout << "[ Col: id: " << col.m_id ndbout << "[ Col: id: " << col.m_id
<< " size: " << col.m_size << " size: " << col.m_size
<< " nulloffset: " << col.m_nulloffset
<< " key: " << (Uint32)(col.m_flags & Restore::Column::COL_KEY) << " key: " << (Uint32)(col.m_flags & Restore::Column::COL_KEY)
<< " variable: " << (Uint32)(col.m_flags & Restore::Column::COL_VAR) << " variable: " << (Uint32)(col.m_flags & Restore::Column::COL_VAR)
<< " null: " << (Uint32)(col.m_flags & Restore::Column::COL_NULL)
<< " disk: " << (Uint32)(col.m_flags & Restore::Column::COL_DISK) << " disk: " << (Uint32)(col.m_flags & Restore::Column::COL_DISK)
<< "]"; << "]";

View File

@ -60,14 +60,15 @@ public:
{ {
Uint16 m_id; Uint16 m_id;
Uint16 m_size; Uint16 m_size;
Uint16 m_nulloffset; // 0 = not nullable Uint16 m_unused;
Uint16 m_flags; Uint16 m_flags;
enum Flags enum Flags
{ {
COL_KEY = 0x1, COL_KEY = 0x1,
COL_VAR = 0x2, COL_VAR = 0x2,
COL_DISK = 0x4 COL_DISK = 0x4,
COL_NULL = 0x8
}; };
}; };
private: private:
@ -98,7 +99,6 @@ private:
Uint32 m_table_version; Uint32 m_table_version;
Uint32 m_fragment_id; Uint32 m_fragment_id;
List::Head m_columns; List::Head m_columns;
Uint32 m_null_bitmask_size;
Uint32 m_current_page_ptr_i; Uint32 m_current_page_ptr_i;
Uint32 m_current_page_pos; Uint32 m_current_page_pos;

View File

@ -14,6 +14,7 @@
along with this program; if not, write to the Free Software along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
#include <my_config.h>
#include "Suma.hpp" #include "Suma.hpp"
#include <ndb_version.h> #include <ndb_version.h>
@ -3149,7 +3150,8 @@ Suma::execSUB_GCP_COMPLETE_REP(Signal* signal)
Page_pos pos= bucket->m_buffer_head; Page_pos pos= bucket->m_buffer_head;
ndbrequire(pos.m_max_gci < gci); ndbrequire(pos.m_max_gci < gci);
Buffer_page* page= (Buffer_page*)(m_tup->cpage+pos.m_page_id); Buffer_page* page= (Buffer_page*)
m_tup->c_page_pool.getPtr(pos.m_page_id);
ndbout_c("takeover %d", pos.m_page_id); ndbout_c("takeover %d", pos.m_page_id);
page->m_max_gci = pos.m_max_gci; page->m_max_gci = pos.m_max_gci;
page->m_words_used = pos.m_page_pos; page->m_words_used = pos.m_page_pos;
@ -4091,7 +4093,7 @@ Suma::get_buffer_ptr(Signal* signal, Uint32 buck, Uint32 gci, Uint32 sz)
Bucket* bucket= c_buckets+buck; Bucket* bucket= c_buckets+buck;
Page_pos pos= bucket->m_buffer_head; Page_pos pos= bucket->m_buffer_head;
Buffer_page* page= (Buffer_page*)(m_tup->cpage+pos.m_page_id); Buffer_page* page= (Buffer_page*)m_tup->c_page_pool.getPtr(pos.m_page_id);
Uint32* ptr= page->m_data + pos.m_page_pos; Uint32* ptr= page->m_data + pos.m_page_pos;
const bool same_gci = (gci == pos.m_last_gci) && (!ERROR_INSERTED(13022)); const bool same_gci = (gci == pos.m_last_gci) && (!ERROR_INSERTED(13022));
@ -4150,7 +4152,7 @@ loop:
pos.m_page_pos = sz; pos.m_page_pos = sz;
pos.m_last_gci = gci; pos.m_last_gci = gci;
page= (Buffer_page*)(m_tup->cpage+pos.m_page_id); page= (Buffer_page*)m_tup->c_page_pool.getPtr(pos.m_page_id);
page->m_next_page= RNIL; page->m_next_page= RNIL;
ptr= page->m_data; ptr= page->m_data;
goto loop; // goto loop; //
@ -4181,7 +4183,7 @@ Suma::out_of_buffer_release(Signal* signal, Uint32 buck)
if(tail != RNIL) if(tail != RNIL)
{ {
Buffer_page* page= (Buffer_page*)(m_tup->cpage+tail); Buffer_page* page= (Buffer_page*)m_tup->c_page_pool.getPtr(tail);
bucket->m_buffer_tail = page->m_next_page; bucket->m_buffer_tail = page->m_next_page;
free_page(tail, page); free_page(tail, page);
signal->theData[0] = SumaContinueB::OUT_OF_BUFFER_RELEASE; signal->theData[0] = SumaContinueB::OUT_OF_BUFFER_RELEASE;
@ -4225,8 +4227,8 @@ loop:
Uint32 ref= m_first_free_page; Uint32 ref= m_first_free_page;
if(likely(ref != RNIL)) if(likely(ref != RNIL))
{ {
m_first_free_page = ((Buffer_page*)m_tup->cpage+ref)->m_next_page; m_first_free_page = ((Buffer_page*)m_tup->c_page_pool.getPtr(ref))->m_next_page;
Uint32 chunk = ((Buffer_page*)m_tup->cpage+ref)->m_page_chunk_ptr_i; Uint32 chunk = ((Buffer_page*)m_tup->c_page_pool.getPtr(ref))->m_page_chunk_ptr_i;
c_page_chunk_pool.getPtr(ptr, chunk); c_page_chunk_pool.getPtr(ptr, chunk);
ndbassert(ptr.p->m_free); ndbassert(ptr.p->m_free);
ptr.p->m_free--; ptr.p->m_free--;
@ -4249,7 +4251,7 @@ loop:
Buffer_page* page; Buffer_page* page;
for(Uint32 i = 0; i<count; i++) for(Uint32 i = 0; i<count; i++)
{ {
page = (Buffer_page*)(m_tup->cpage+ref); page = (Buffer_page*)m_tup->c_page_pool.getPtr(ref);
page->m_page_state= SUMA_SEQUENCE; page->m_page_state= SUMA_SEQUENCE;
page->m_page_chunk_ptr_i = ptr.i; page->m_page_chunk_ptr_i = ptr.i;
page->m_next_page = ++ref; page->m_next_page = ++ref;
@ -4313,7 +4315,7 @@ Suma::release_gci(Signal* signal, Uint32 buck, Uint32 gci)
else else
{ {
jam(); jam();
Buffer_page* page= (Buffer_page*)(m_tup->cpage+tail); Buffer_page* page= (Buffer_page*)m_tup->c_page_pool.getPtr(tail);
Uint32 max_gci = page->m_max_gci; Uint32 max_gci = page->m_max_gci;
Uint32 next_page = page->m_next_page; Uint32 next_page = page->m_next_page;
@ -4406,7 +4408,7 @@ Suma::resend_bucket(Signal* signal, Uint32 buck, Uint32 min_gci,
Bucket* bucket= c_buckets+buck; Bucket* bucket= c_buckets+buck;
Uint32 tail= bucket->m_buffer_tail; Uint32 tail= bucket->m_buffer_tail;
Buffer_page* page= (Buffer_page*)(m_tup->cpage+tail); Buffer_page* page= (Buffer_page*)m_tup->c_page_pool.getPtr(tail);
Uint32 max_gci = page->m_max_gci; Uint32 max_gci = page->m_max_gci;
Uint32 next_page = page->m_next_page; Uint32 next_page = page->m_next_page;
Uint32 *ptr = page->m_data + pos; Uint32 *ptr = page->m_data + pos;

View File

@ -390,7 +390,6 @@ Tsman::execDROP_FILEGROUP_REQ(Signal* signal){
if (errorCode) if (errorCode)
{ {
ndbassert(false);
DropFilegroupImplRef* ref = DropFilegroupImplRef* ref =
(DropFilegroupImplRef*)signal->getDataPtrSend(); (DropFilegroupImplRef*)signal->getDataPtrSend();
ref->senderRef = reference(); ref->senderRef = reference();
@ -1084,7 +1083,9 @@ Tsman::load_extent_page_callback(Signal* signal,
Ptr<Tablespace> ts_ptr; Ptr<Tablespace> ts_ptr;
m_tablespace_pool.getPtr(ts_ptr, ptr.p->m_tablespace_ptr_i); m_tablespace_pool.getPtr(ts_ptr, ptr.p->m_tablespace_ptr_i);
if (!getNodeState().getSystemRestartInProgress()) if (getNodeState().startLevel >= NodeState::SL_STARTED ||
(getNodeState().getNodeRestartInProgress() &&
getNodeState().starting.restartType == NodeState::ST_INITIAL_NODE_RESTART))
{ {
LocalDLList<Datafile> free(m_file_pool, ts_ptr.p->m_free_files); LocalDLList<Datafile> free(m_file_pool, ts_ptr.p->m_free_files);
LocalDLList<Datafile> meta(m_file_pool, ts_ptr.p->m_meta_files); LocalDLList<Datafile> meta(m_file_pool, ts_ptr.p->m_meta_files);
@ -1614,6 +1615,57 @@ Tsman::update_page_free_bits(Signal* signal,
return AllocExtentReq::UnmappedExtentPageIsNotImplemented; return AllocExtentReq::UnmappedExtentPageIsNotImplemented;
} }
int
Tsman::get_page_free_bits(Signal* signal, Local_key *key, unsigned* bits)
{
jamEntry();
/**
* XXX make into subroutine
*/
Ptr<Datafile> file_ptr;
Datafile file_key;
file_key.m_file_no = key->m_file_no;
ndbrequire(m_file_hash.find(file_ptr, file_key));
Uint32 size = file_ptr.p->m_extent_size;
Uint32 data_off = file_ptr.p->m_online.m_offset_data_pages;
Uint32 eh_words = File_formats::Datafile::extent_header_words(size);
Uint32 per_page = File_formats::Datafile::EXTENT_PAGE_WORDS/eh_words;
Uint32 SZ= File_formats::Datafile::EXTENT_HEADER_BITMASK_BITS_PER_PAGE;
Uint32 extent = (key->m_page_no - data_off) / size + per_page;
Uint32 page_no = extent / per_page;
Uint32 extent_no = extent % per_page;
Page_cache_client::Request preq;
preq.m_page.m_page_no = page_no;
preq.m_page.m_file_no = key->m_file_no;
/**
* Handling of unmapped extent header pages is not implemented
*/
int flags = 0;
int real_page_id;
if ((real_page_id = m_page_cache_client.get_page(signal, preq, flags)) > 0)
{
GlobalPage* ptr_p = m_page_cache_client.m_ptr.p;
File_formats::Datafile::Extent_page* page =
(File_formats::Datafile::Extent_page*)ptr_p;
File_formats::Datafile::Extent_header* header =
page->get_header(extent_no, size);
ndbrequire(header->m_table != RNIL);
Uint32 page_no_in_extent = (key->m_page_no - data_off) % size;
*bits = header->get_free_bits(page_no_in_extent);
return 0;
}
return AllocExtentReq::UnmappedExtentPageIsNotImplemented;
}
int int
Tsman::unmap_page(Signal* signal, Local_key *key) Tsman::unmap_page(Signal* signal, Local_key *key)
{ {
@ -2056,15 +2108,21 @@ void Tsman::execGET_TABINFOREQ(Signal* signal)
jam(); jam();
releaseSections(signal); releaseSections(signal);
sendGET_TABINFOREF(signal, req, GetTabInfoRef::TableNameTooLong); sendGET_TABINFOREF(signal, req, GetTabInfoRef::NoFetchByName);
return; return;
} }
DLHashTable<Datafile>::Iterator iter; DLHashTable<Datafile>::Iterator iter;
ndbrequire(m_file_hash.first(iter)); ndbrequire(m_file_hash.first(iter));
while(iter.curr.p->m_file_id != tableId && m_file_hash.next(iter)) while(iter.curr.p->m_file_id != tableId && m_file_hash.next(iter))
; ;
ndbrequire(iter.curr.p->m_file_id == tableId);
if(iter.curr.p->m_file_id != tableId)
{
sendGET_TABINFOREF(signal, req, GetTabInfoRef::InvalidTableId);
return;
}
const Ptr<Datafile> &file_ptr= iter.curr; const Ptr<Datafile> &file_ptr= iter.curr;

View File

@ -196,6 +196,7 @@ private:
void create_file_ref(Signal*, Ptr<Tablespace>, Ptr<Datafile>, void create_file_ref(Signal*, Ptr<Tablespace>, Ptr<Datafile>,
Uint32,Uint32,Uint32); Uint32,Uint32,Uint32);
int update_page_free_bits(Signal*, Local_key*, unsigned bits, Uint64 lsn); int update_page_free_bits(Signal*, Local_key*, unsigned bits, Uint64 lsn);
int get_page_free_bits(Signal*, Local_key*, unsigned* bits);
int unmap_page(Signal*, Local_key*); int unmap_page(Signal*, Local_key*);
int restart_undo_page_free_bits(Signal*, Local_key*, unsigned, Uint64); int restart_undo_page_free_bits(Signal*, Local_key*, unsigned, Uint64);
@ -266,6 +267,11 @@ public:
*/ */
int update_page_free_bits(Local_key*, unsigned bits, Uint64 lsn); int update_page_free_bits(Local_key*, unsigned bits, Uint64 lsn);
/**
* Get page free bits
*/
int get_page_free_bits(Local_key*, unsigned* bits);
/** /**
* Update unlogged page free bit * Update unlogged page free bit
*/ */
@ -352,6 +358,13 @@ Tablespace_client::update_page_free_bits(Local_key *key,
return m_tsman->update_page_free_bits(m_signal, key, bits, lsn); return m_tsman->update_page_free_bits(m_signal, key, bits, lsn);
} }
inline
int
Tablespace_client::get_page_free_bits(Local_key *key, unsigned* bits)
{
return m_tsman->get_page_free_bits(m_signal, key, bits);
}
inline inline
int int
Tablespace_client::unmap_page(Local_key *key) Tablespace_client::unmap_page(Local_key *key)

View File

@ -42,7 +42,8 @@ public:
* *
* Note, can currently only be called once * Note, can currently only be called once
*/ */
bool setSize(Uint32 noOfElements, bool align = false, bool exit_on_error = true); bool setSize(Uint32 noOfElements, bool align = false, bool exit_on_error = true, bool guard = true);
bool set(T*, Uint32 cnt, bool align = false);
inline Uint32 getNoOfFree() const { inline Uint32 getNoOfFree() const {
return noOfFree; return noOfFree;
@ -202,6 +203,7 @@ ArrayPool<T>::~ArrayPool(){
theArray = 0; theArray = 0;
alloc_ptr = 0; alloc_ptr = 0;
#ifdef ARRAY_GUARD #ifdef ARRAY_GUARD
if (theAllocatedBitmask)
delete []theAllocatedBitmask; delete []theAllocatedBitmask;
theAllocatedBitmask = 0; theAllocatedBitmask = 0;
#endif #endif
@ -216,7 +218,8 @@ ArrayPool<T>::~ArrayPool(){
template <class T> template <class T>
inline inline
bool bool
ArrayPool<T>::setSize(Uint32 noOfElements, bool align, bool exit_on_error){ ArrayPool<T>::setSize(Uint32 noOfElements,
bool align, bool exit_on_error, bool guard){
if(size == 0){ if(size == 0){
if(noOfElements == 0) if(noOfElements == 0)
return true; return true;
@ -257,9 +260,12 @@ ArrayPool<T>::setSize(Uint32 noOfElements, bool align, bool exit_on_error){
firstFree = 0; firstFree = 0;
#ifdef ARRAY_GUARD #ifdef ARRAY_GUARD
if (guard)
{
bitmaskSz = (noOfElements + 31) >> 5; bitmaskSz = (noOfElements + 31) >> 5;
theAllocatedBitmask = new Uint32[bitmaskSz]; theAllocatedBitmask = new Uint32[bitmaskSz];
BitmaskImpl::clear(bitmaskSz, theAllocatedBitmask); BitmaskImpl::clear(bitmaskSz, theAllocatedBitmask);
}
#endif #endif
return true; return true;
@ -271,20 +277,55 @@ ArrayPool<T>::setSize(Uint32 noOfElements, bool align, bool exit_on_error){
return false; // not reached return false; // not reached
} }
template <class T>
inline
bool
ArrayPool<T>::set(T* ptr, Uint32 cnt, bool align){
if (size == 0)
{
alloc_ptr = ptr;
if(align)
{
UintPtr p = (UintPtr)alloc_ptr;
UintPtr mod = p % sizeof(T);
if (mod)
{
p += sizeof(T) - mod;
cnt --;
}
theArray = (T *)p;
}
else
{
theArray = (T *)alloc_ptr;
}
size = cnt;
noOfFree = 0;
return true;
}
ErrorReporter::handleAssert("ArrayPool<T>::set called twice",
__FILE__, __LINE__);
return false; // not reached
}
template <class T> template <class T>
inline inline
void void
ArrayPool<T>::getPtr(Ptr<T> & ptr){ ArrayPool<T>::getPtr(Ptr<T> & ptr){
Uint32 i = ptr.i; Uint32 i = ptr.i;
if(i < size){ if(likely (i < size)){
ptr.p = &theArray[i]; ptr.p = &theArray[i];
#ifdef ARRAY_GUARD #ifdef ARRAY_GUARD
if (theAllocatedBitmask)
{
if(BitmaskImpl::get(bitmaskSz, theAllocatedBitmask, i)) if(BitmaskImpl::get(bitmaskSz, theAllocatedBitmask, i))
return; return;
/** /**
* Getting a non-seized element * Getting a non-seized element
*/ */
ErrorReporter::handleAssert("ArrayPool<T>::getPtr", __FILE__, __LINE__); ErrorReporter::handleAssert("ArrayPool<T>::getPtr", __FILE__, __LINE__);
}
#endif #endif
} else { } else {
ErrorReporter::handleAssert("ArrayPool<T>::getPtr", __FILE__, __LINE__); ErrorReporter::handleAssert("ArrayPool<T>::getPtr", __FILE__, __LINE__);
@ -296,15 +337,18 @@ inline
void void
ArrayPool<T>::getPtr(ConstPtr<T> & ptr) const { ArrayPool<T>::getPtr(ConstPtr<T> & ptr) const {
Uint32 i = ptr.i; Uint32 i = ptr.i;
if(i < size){ if(likely(i < size)){
ptr.p = &theArray[i]; ptr.p = &theArray[i];
#ifdef ARRAY_GUARD #ifdef ARRAY_GUARD
if (theAllocatedBitmask)
{
if(BitmaskImpl::get(bitmaskSz, theAllocatedBitmask, i)) if(BitmaskImpl::get(bitmaskSz, theAllocatedBitmask, i))
return; return;
/** /**
* Getting a non-seized element * Getting a non-seized element
*/ */
ErrorReporter::handleAssert("ArrayPool<T>::getPtr", __FILE__, __LINE__); ErrorReporter::handleAssert("ArrayPool<T>::getPtr", __FILE__, __LINE__);
}
#endif #endif
} else { } else {
ErrorReporter::handleAssert("ArrayPool<T>::getPtr", __FILE__, __LINE__); ErrorReporter::handleAssert("ArrayPool<T>::getPtr", __FILE__, __LINE__);
@ -316,15 +360,18 @@ inline
void void
ArrayPool<T>::getPtr(Ptr<T> & ptr, Uint32 i){ ArrayPool<T>::getPtr(Ptr<T> & ptr, Uint32 i){
ptr.i = i; ptr.i = i;
if(i < size){ if(likely(i < size)){
ptr.p = &theArray[i]; ptr.p = &theArray[i];
#ifdef ARRAY_GUARD #ifdef ARRAY_GUARD
if (theAllocatedBitmask)
{
if(BitmaskImpl::get(bitmaskSz, theAllocatedBitmask, i)) if(BitmaskImpl::get(bitmaskSz, theAllocatedBitmask, i))
return; return;
/** /**
* Getting a non-seized element * Getting a non-seized element
*/ */
ErrorReporter::handleAssert("ArrayPool<T>::getPtr", __FILE__, __LINE__); ErrorReporter::handleAssert("ArrayPool<T>::getPtr", __FILE__, __LINE__);
}
#endif #endif
} else { } else {
ErrorReporter::handleAssert("ArrayPool<T>::getPtr", __FILE__, __LINE__); ErrorReporter::handleAssert("ArrayPool<T>::getPtr", __FILE__, __LINE__);
@ -336,15 +383,18 @@ inline
void void
ArrayPool<T>::getPtr(ConstPtr<T> & ptr, Uint32 i) const { ArrayPool<T>::getPtr(ConstPtr<T> & ptr, Uint32 i) const {
ptr.i = i; ptr.i = i;
if(i < size){ if(likely(i < size)){
ptr.p = &theArray[i]; ptr.p = &theArray[i];
#ifdef ARRAY_GUARD #ifdef ARRAY_GUARD
if (theAllocatedBitmask)
{
if(BitmaskImpl::get(bitmaskSz, theAllocatedBitmask, i)) if(BitmaskImpl::get(bitmaskSz, theAllocatedBitmask, i))
return; return;
/** /**
* Getting a non-seized element * Getting a non-seized element
*/ */
ErrorReporter::handleAssert("ArrayPool<T>::getPtr", __FILE__, __LINE__); ErrorReporter::handleAssert("ArrayPool<T>::getPtr", __FILE__, __LINE__);
}
#endif #endif
} else { } else {
ErrorReporter::handleAssert("ArrayPool<T>::getPtr", __FILE__, __LINE__); ErrorReporter::handleAssert("ArrayPool<T>::getPtr", __FILE__, __LINE__);
@ -355,8 +405,10 @@ template <class T>
inline inline
T * T *
ArrayPool<T>::getPtr(Uint32 i){ ArrayPool<T>::getPtr(Uint32 i){
if(i < size){ if(likely(i < size)){
#ifdef ARRAY_GUARD #ifdef ARRAY_GUARD
if (theAllocatedBitmask)
{
if(BitmaskImpl::get(bitmaskSz, theAllocatedBitmask, i)) if(BitmaskImpl::get(bitmaskSz, theAllocatedBitmask, i))
return &theArray[i]; return &theArray[i];
/** /**
@ -364,9 +416,9 @@ ArrayPool<T>::getPtr(Uint32 i){
*/ */
ErrorReporter::handleAssert("ArrayPool<T>::getPtr", __FILE__, __LINE__); ErrorReporter::handleAssert("ArrayPool<T>::getPtr", __FILE__, __LINE__);
return 0; return 0;
#else }
return &theArray[i];
#endif #endif
return &theArray[i];
} else { } else {
ErrorReporter::handleAssert("ArrayPool<T>::getPtr", __FILE__, __LINE__); ErrorReporter::handleAssert("ArrayPool<T>::getPtr", __FILE__, __LINE__);
return 0; return 0;
@ -377,8 +429,10 @@ template <class T>
inline inline
const T * const T *
ArrayPool<T>::getConstPtr(Uint32 i) const { ArrayPool<T>::getConstPtr(Uint32 i) const {
if(i < size){ if(likely(i < size)){
#ifdef ARRAY_GUARD #ifdef ARRAY_GUARD
if (theAllocatedBitmask)
{
if(BitmaskImpl::get(bitmaskSz, theAllocatedBitmask, i)) if(BitmaskImpl::get(bitmaskSz, theAllocatedBitmask, i))
return &theArray[i]; return &theArray[i];
/** /**
@ -386,9 +440,9 @@ ArrayPool<T>::getConstPtr(Uint32 i) const {
*/ */
ErrorReporter::handleAssert("ArrayPool<T>::getPtr", __FILE__, __LINE__); ErrorReporter::handleAssert("ArrayPool<T>::getPtr", __FILE__, __LINE__);
return 0; return 0;
#else }
return &theArray[i];
#endif #endif
return &theArray[i];
} else { } else {
ErrorReporter::handleAssert("ArrayPool<T>::getPtr", __FILE__, __LINE__); ErrorReporter::handleAssert("ArrayPool<T>::getPtr", __FILE__, __LINE__);
return 0; return 0;
@ -400,15 +454,18 @@ inline
void void
ArrayPool<T>::getPtr(Ptr<T> & ptr, bool CrashOnBoundaryError){ ArrayPool<T>::getPtr(Ptr<T> & ptr, bool CrashOnBoundaryError){
Uint32 i = ptr.i; Uint32 i = ptr.i;
if(i < size){ if(likely(i < size)){
ptr.p = &theArray[i]; ptr.p = &theArray[i];
#ifdef ARRAY_GUARD #ifdef ARRAY_GUARD
if (theAllocatedBitmask)
{
if(BitmaskImpl::get(bitmaskSz, theAllocatedBitmask, i)) if(BitmaskImpl::get(bitmaskSz, theAllocatedBitmask, i))
return; return;
/** /**
* Getting a non-seized element * Getting a non-seized element
*/ */
ErrorReporter::handleAssert("ArrayPool<T>::getPtr", __FILE__, __LINE__); ErrorReporter::handleAssert("ArrayPool<T>::getPtr", __FILE__, __LINE__);
}
#endif #endif
} else { } else {
ptr.i = RNIL; ptr.i = RNIL;
@ -420,15 +477,18 @@ inline
void void
ArrayPool<T>::getPtr(ConstPtr<T> & ptr, bool CrashOnBoundaryError) const { ArrayPool<T>::getPtr(ConstPtr<T> & ptr, bool CrashOnBoundaryError) const {
Uint32 i = ptr.i; Uint32 i = ptr.i;
if(i < size){ if(likely(i < size)){
ptr.p = &theArray[i]; ptr.p = &theArray[i];
#ifdef ARRAY_GUARD #ifdef ARRAY_GUARD
if (theAllocatedBitmask)
{
if(BitmaskImpl::get(bitmaskSz, theAllocatedBitmask, i)) if(BitmaskImpl::get(bitmaskSz, theAllocatedBitmask, i))
return; return;
/** /**
* Getting a non-seized element * Getting a non-seized element
*/ */
ErrorReporter::handleAssert("ArrayPool<T>::getPtr", __FILE__, __LINE__); ErrorReporter::handleAssert("ArrayPool<T>::getPtr", __FILE__, __LINE__);
}
#endif #endif
} else { } else {
ptr.i = RNIL; ptr.i = RNIL;
@ -440,15 +500,18 @@ inline
void void
ArrayPool<T>::getPtr(Ptr<T> & ptr, Uint32 i, bool CrashOnBoundaryError){ ArrayPool<T>::getPtr(Ptr<T> & ptr, Uint32 i, bool CrashOnBoundaryError){
ptr.i = i; ptr.i = i;
if(i < size){ if(likely(i < size)){
ptr.p = &theArray[i]; ptr.p = &theArray[i];
#ifdef ARRAY_GUARD #ifdef ARRAY_GUARD
if (theAllocatedBitmask)
{
if(BitmaskImpl::get(bitmaskSz, theAllocatedBitmask, i)) if(BitmaskImpl::get(bitmaskSz, theAllocatedBitmask, i))
return; return;
/** /**
* Getting a non-seized element * Getting a non-seized element
*/ */
ErrorReporter::handleAssert("ArrayPool<T>::getPtr", __FILE__, __LINE__); ErrorReporter::handleAssert("ArrayPool<T>::getPtr", __FILE__, __LINE__);
}
#endif #endif
} else { } else {
ptr.i = RNIL; ptr.i = RNIL;
@ -461,15 +524,18 @@ void
ArrayPool<T>::getPtr(ConstPtr<T> & ptr, Uint32 i, ArrayPool<T>::getPtr(ConstPtr<T> & ptr, Uint32 i,
bool CrashOnBoundaryError) const { bool CrashOnBoundaryError) const {
ptr.i = i; ptr.i = i;
if(i < size){ if(likely(i < size)){
ptr.p = &theArray[i]; ptr.p = &theArray[i];
#ifdef ARRAY_GUARD #ifdef ARRAY_GUARD
if (theAllocatedBitmask)
{
if(BitmaskImpl::get(bitmaskSz, theAllocatedBitmask, i)) if(BitmaskImpl::get(bitmaskSz, theAllocatedBitmask, i))
return; return;
/** /**
* Getting a non-seized element * Getting a non-seized element
*/ */
ErrorReporter::handleAssert("ArrayPool<T>::getPtr", __FILE__, __LINE__); ErrorReporter::handleAssert("ArrayPool<T>::getPtr", __FILE__, __LINE__);
}
#endif #endif
} else { } else {
ptr.i = RNIL; ptr.i = RNIL;
@ -480,8 +546,10 @@ template <class T>
inline inline
T * T *
ArrayPool<T>::getPtr(Uint32 i, bool CrashOnBoundaryError){ ArrayPool<T>::getPtr(Uint32 i, bool CrashOnBoundaryError){
if(i < size){ if(likely(i < size)){
#ifdef ARRAY_GUARD #ifdef ARRAY_GUARD
if (theAllocatedBitmask)
{
if(BitmaskImpl::get(bitmaskSz, theAllocatedBitmask, i)) if(BitmaskImpl::get(bitmaskSz, theAllocatedBitmask, i))
return &theArray[i]; return &theArray[i];
/** /**
@ -489,9 +557,9 @@ ArrayPool<T>::getPtr(Uint32 i, bool CrashOnBoundaryError){
*/ */
ErrorReporter::handleAssert("ArrayPool<T>::getPtr", __FILE__, __LINE__); ErrorReporter::handleAssert("ArrayPool<T>::getPtr", __FILE__, __LINE__);
return 0; return 0;
#else }
return &theArray[i];
#endif #endif
return &theArray[i];
} else { } else {
return 0; return 0;
} }
@ -501,8 +569,10 @@ template <class T>
inline inline
const T * const T *
ArrayPool<T>::getConstPtr(Uint32 i, bool CrashOnBoundaryError) const { ArrayPool<T>::getConstPtr(Uint32 i, bool CrashOnBoundaryError) const {
if(i < size){ if(likely(i < size)){
#ifdef ARRAY_GUARD #ifdef ARRAY_GUARD
if (theAllocatedBitmask)
{
if(BitmaskImpl::get(bitmaskSz, theAllocatedBitmask, i)) if(BitmaskImpl::get(bitmaskSz, theAllocatedBitmask, i))
return &theArray[i]; return &theArray[i];
/** /**
@ -510,9 +580,9 @@ ArrayPool<T>::getConstPtr(Uint32 i, bool CrashOnBoundaryError) const {
*/ */
ErrorReporter::handleAssert("ArrayPool<T>::getConstPtr", __FILE__,__LINE__); ErrorReporter::handleAssert("ArrayPool<T>::getConstPtr", __FILE__,__LINE__);
return 0; return 0;
#else }
return &theArray[i];
#endif #endif
return &theArray[i];
} else { } else {
return 0; return 0;
} }
@ -534,6 +604,8 @@ ArrayPool<T>::seize(Ptr<T> & ptr){
ptr.i = ff; ptr.i = ff;
ptr.p = &theArray[ff]; ptr.p = &theArray[ff];
#ifdef ARRAY_GUARD #ifdef ARRAY_GUARD
if (theAllocatedBitmask)
{
if(!BitmaskImpl::get(bitmaskSz, theAllocatedBitmask, ff)){ if(!BitmaskImpl::get(bitmaskSz, theAllocatedBitmask, ff)){
BitmaskImpl::set(bitmaskSz, theAllocatedBitmask, ff); BitmaskImpl::set(bitmaskSz, theAllocatedBitmask, ff);
noOfFree--; noOfFree--;
@ -545,10 +617,10 @@ ArrayPool<T>::seize(Ptr<T> & ptr){
ErrorReporter::handleAssert("ArrayPool<T>::seize", __FILE__, __LINE__); ErrorReporter::handleAssert("ArrayPool<T>::seize", __FILE__, __LINE__);
return false; return false;
} }
#else }
#endif
noOfFree--; noOfFree--;
return true; return true;
#endif
} }
ptr.i = RNIL; ptr.i = RNIL;
ptr.p = NULL; ptr.p = NULL;
@ -575,6 +647,8 @@ ArrayPool<T>::seizeId(Ptr<T> & ptr, Uint32 i){
ptr.i = ff; ptr.i = ff;
ptr.p = &theArray[ff]; ptr.p = &theArray[ff];
#ifdef ARRAY_GUARD #ifdef ARRAY_GUARD
if (theAllocatedBitmask)
{
if(!BitmaskImpl::get(bitmaskSz, theAllocatedBitmask, ff)){ if(!BitmaskImpl::get(bitmaskSz, theAllocatedBitmask, ff)){
BitmaskImpl::set(bitmaskSz, theAllocatedBitmask, ff); BitmaskImpl::set(bitmaskSz, theAllocatedBitmask, ff);
noOfFree--; noOfFree--;
@ -586,10 +660,10 @@ ArrayPool<T>::seizeId(Ptr<T> & ptr, Uint32 i){
ErrorReporter::handleAssert("ArrayPool<T>::seizeId", __FILE__, __LINE__); ErrorReporter::handleAssert("ArrayPool<T>::seizeId", __FILE__, __LINE__);
return false; return false;
} }
#else }
#endif
noOfFree--; noOfFree--;
return true; return true;
#endif
} }
ptr.i = RNIL; ptr.i = RNIL;
ptr.p = NULL; ptr.p = NULL;
@ -636,6 +710,8 @@ ArrayPool<T>::seizeN(Uint32 n){
noOfFree -= n; noOfFree -= n;
#ifdef ARRAY_GUARD #ifdef ARRAY_GUARD
if (theAllocatedBitmask)
{
for(Uint32 j = base; j<curr; j++){ for(Uint32 j = base; j<curr; j++){
if(!BitmaskImpl::get(bitmaskSz, theAllocatedBitmask, j)){ if(!BitmaskImpl::get(bitmaskSz, theAllocatedBitmask, j)){
BitmaskImpl::set(bitmaskSz, theAllocatedBitmask, j); BitmaskImpl::set(bitmaskSz, theAllocatedBitmask, j);
@ -647,6 +723,7 @@ ArrayPool<T>::seizeN(Uint32 n){
return RNIL; return RNIL;
} }
} }
}
#endif #endif
return base; return base;
} }
@ -669,6 +746,8 @@ ArrayPool<T>::releaseN(Uint32 base, Uint32 n){
const Uint32 end = base + n; const Uint32 end = base + n;
for(Uint32 i = base; i<end; i++){ for(Uint32 i = base; i<end; i++){
#ifdef ARRAY_GUARD #ifdef ARRAY_GUARD
if (theAllocatedBitmask)
{
if(BitmaskImpl::get(bitmaskSz, theAllocatedBitmask, i)){ if(BitmaskImpl::get(bitmaskSz, theAllocatedBitmask, i)){
BitmaskImpl::clear(bitmaskSz, theAllocatedBitmask, i); BitmaskImpl::clear(bitmaskSz, theAllocatedBitmask, i);
} else { } else {
@ -678,6 +757,7 @@ ArrayPool<T>::releaseN(Uint32 base, Uint32 n){
ErrorReporter::handleAssert("ArrayPool<T>::release", __FILE__, __LINE__); ErrorReporter::handleAssert("ArrayPool<T>::release", __FILE__, __LINE__);
return; return;
} }
}
#endif #endif
theArray[i].nextPool = i + 1; theArray[i].nextPool = i + 1;
} }
@ -697,6 +777,8 @@ ArrayPool<T>::releaseList(Uint32 n, Uint32 first, Uint32 last){
noOfFree += n; noOfFree += n;
#ifdef ARRAY_GUARD #ifdef ARRAY_GUARD
if (theAllocatedBitmask)
{
Uint32 tmp = first; Uint32 tmp = first;
for(Uint32 i = 0; i<n; i++){ for(Uint32 i = 0; i<n; i++){
if(BitmaskImpl::get(bitmaskSz, theAllocatedBitmask, tmp)){ if(BitmaskImpl::get(bitmaskSz, theAllocatedBitmask, tmp)){
@ -711,6 +793,7 @@ ArrayPool<T>::releaseList(Uint32 n, Uint32 first, Uint32 last){
} }
tmp = theArray[tmp].nextPool; tmp = theArray[tmp].nextPool;
} }
}
#endif #endif
return; return;
} }
@ -725,12 +808,14 @@ inline
void void
ArrayPool<T>::release(Uint32 _i){ ArrayPool<T>::release(Uint32 _i){
const Uint32 i = _i; const Uint32 i = _i;
if(i < size){ if(likely(i < size)){
Uint32 ff = firstFree; Uint32 ff = firstFree;
theArray[i].nextPool = ff; theArray[i].nextPool = ff;
firstFree = i; firstFree = i;
#ifdef ARRAY_GUARD #ifdef ARRAY_GUARD
if (theAllocatedBitmask)
{
if(BitmaskImpl::get(bitmaskSz, theAllocatedBitmask, i)){ if(BitmaskImpl::get(bitmaskSz, theAllocatedBitmask, i)){
BitmaskImpl::clear(bitmaskSz, theAllocatedBitmask, i); BitmaskImpl::clear(bitmaskSz, theAllocatedBitmask, i);
noOfFree++; noOfFree++;
@ -740,6 +825,7 @@ ArrayPool<T>::release(Uint32 _i){
* Relesing a already released element * Relesing a already released element
*/ */
ErrorReporter::handleAssert("ArrayPool<T>::release", __FILE__, __LINE__); ErrorReporter::handleAssert("ArrayPool<T>::release", __FILE__, __LINE__);
}
#endif #endif
noOfFree++; noOfFree++;
return; return;
@ -755,12 +841,14 @@ inline
void void
ArrayPool<T>::release(Ptr<T> & ptr){ ArrayPool<T>::release(Ptr<T> & ptr){
Uint32 i = ptr.i; Uint32 i = ptr.i;
if(i < size){ if(likely(i < size)){
Uint32 ff = firstFree; Uint32 ff = firstFree;
theArray[i].nextPool = ff; theArray[i].nextPool = ff;
firstFree = i; firstFree = i;
#ifdef ARRAY_GUARD #ifdef ARRAY_GUARD
if (theAllocatedBitmask)
{
if(BitmaskImpl::get(bitmaskSz, theAllocatedBitmask, i)){ if(BitmaskImpl::get(bitmaskSz, theAllocatedBitmask, i)){
BitmaskImpl::clear(bitmaskSz, theAllocatedBitmask, i); BitmaskImpl::clear(bitmaskSz, theAllocatedBitmask, i);
//assert(noOfFree() == noOfFree2()); //assert(noOfFree() == noOfFree2());
@ -771,6 +859,7 @@ ArrayPool<T>::release(Ptr<T> & ptr){
* Relesing a already released element * Relesing a already released element
*/ */
ErrorReporter::handleAssert("ArrayPool<T>::release", __FILE__, __LINE__); ErrorReporter::handleAssert("ArrayPool<T>::release", __FILE__, __LINE__);
}
#endif #endif
noOfFree++; noOfFree++;
return; return;
@ -798,7 +887,7 @@ inline
void void
UnsafeArrayPool<T>::getPtrForce(Ptr<T> & ptr){ UnsafeArrayPool<T>::getPtrForce(Ptr<T> & ptr){
Uint32 i = ptr.i; Uint32 i = ptr.i;
if(i < this->size){ if(likely(i < this->size)){
ptr.p = &this->theArray[i]; ptr.p = &this->theArray[i];
} else { } else {
ErrorReporter::handleAssert("UnsafeArrayPool<T>::getPtr", ErrorReporter::handleAssert("UnsafeArrayPool<T>::getPtr",
@ -811,7 +900,7 @@ inline
void void
UnsafeArrayPool<T>::getPtrForce(ConstPtr<T> & ptr) const{ UnsafeArrayPool<T>::getPtrForce(ConstPtr<T> & ptr) const{
Uint32 i = ptr.i; Uint32 i = ptr.i;
if(i < this->size){ if(likely(i < this->size)){
ptr.p = &this->theArray[i]; ptr.p = &this->theArray[i];
} else { } else {
ErrorReporter::handleAssert("UnsafeArrayPool<T>::getPtr", ErrorReporter::handleAssert("UnsafeArrayPool<T>::getPtr",
@ -823,7 +912,7 @@ template <class T>
inline inline
T * T *
UnsafeArrayPool<T>::getPtrForce(Uint32 i){ UnsafeArrayPool<T>::getPtrForce(Uint32 i){
if(i < this->size){ if(likely(i < this->size)){
return &this->theArray[i]; return &this->theArray[i];
} else { } else {
ErrorReporter::handleAssert("UnsafeArrayPool<T>::getPtr", ErrorReporter::handleAssert("UnsafeArrayPool<T>::getPtr",
@ -836,7 +925,7 @@ template <class T>
inline inline
const T * const T *
UnsafeArrayPool<T>::getConstPtrForce(Uint32 i) const { UnsafeArrayPool<T>::getConstPtrForce(Uint32 i) const {
if(i < this->size){ if(likely(i < this->size)){
return &this->theArray[i]; return &this->theArray[i];
} else { } else {
ErrorReporter::handleAssert("UnsafeArrayPool<T>::getPtr", ErrorReporter::handleAssert("UnsafeArrayPool<T>::getPtr",
@ -850,7 +939,7 @@ inline
void void
UnsafeArrayPool<T>::getPtrForce(Ptr<T> & ptr, Uint32 i){ UnsafeArrayPool<T>::getPtrForce(Ptr<T> & ptr, Uint32 i){
ptr.i = i; ptr.i = i;
if(i < this->size){ if(likely(i < this->size)){
ptr.p = &this->theArray[i]; ptr.p = &this->theArray[i];
return ; return ;
} else { } else {
@ -864,7 +953,7 @@ inline
void void
UnsafeArrayPool<T>::getPtrForce(ConstPtr<T> & ptr, Uint32 i) const{ UnsafeArrayPool<T>::getPtrForce(ConstPtr<T> & ptr, Uint32 i) const{
ptr.i = i; ptr.i = i;
if(i < this->size){ if(likely(i < this->size)){
ptr.p = &this->theArray[i]; ptr.p = &this->theArray[i];
return ; return ;
} else { } else {

View File

@ -92,6 +92,12 @@ public:
*/ */
void add(Ptr<T> &); void add(Ptr<T> &);
/**
* Add a list to list
* @NOTE all elements _must_ be correctly initilized correctly wrt next/prev
*/
void add(Uint32 first, Ptr<T> & last);
/** /**
* Remove object from list * Remove object from list
* *
@ -99,6 +105,13 @@ public:
*/ */
void remove(Ptr<T> &); void remove(Ptr<T> &);
/**
* Remove object from list
*
* @NOTE Does not return it to pool
*/
void remove(T*);
/** /**
* Update i & p value according to <b>i</b> * Update i & p value according to <b>i</b>
*/ */
@ -253,22 +266,45 @@ DLList<T,U>::add(Ptr<T> & p){
} }
} }
template <class T, class U>
inline
void
DLList<T,U>::add(Uint32 first, Ptr<T> & lastPtr)
{
Uint32 ff = head.firstItem;
head.firstItem = first;
lastPtr.p->U::nextList = ff;
if(ff != RNIL){
T * t2 = thePool.getPtr(ff);
t2->U::prevList = lastPtr.i;
}
}
template <class T, class U> template <class T, class U>
inline inline
void void
DLList<T,U>::remove(Ptr<T> & p){ DLList<T,U>::remove(Ptr<T> & p){
T * t = p.p; remove(p.p);
}
template <class T, class U>
inline
void
DLList<T,U>::remove(T * p){
T * t = p;
Uint32 ni = t->U::nextList; Uint32 ni = t->U::nextList;
Uint32 pi = t->U::prevList; Uint32 pi = t->U::prevList;
if(ni != RNIL){ if(ni != RNIL){
T * t = thePool.getPtr(ni); T * tn = thePool.getPtr(ni);
t->U::prevList = pi; tn->U::prevList = pi;
} }
if(pi != RNIL){ if(pi != RNIL){
T * t = thePool.getPtr(pi); T * tp = thePool.getPtr(pi);
t->U::nextList = ni; tp->U::nextList = ni;
} else { } else {
head.firstItem = ni; head.firstItem = ni;
} }

View File

@ -20,7 +20,7 @@ libkernel_a_SOURCES = \
Mutex.cpp SafeCounter.cpp \ Mutex.cpp SafeCounter.cpp \
Rope.cpp \ Rope.cpp \
SuperPool.cpp \ SuperPool.cpp \
ndbd_malloc.cpp ndbd_malloc.cpp ndbd_malloc_impl.cpp
INCLUDES_LOC = -I$(top_srcdir)/storage/ndb/src/mgmapi INCLUDES_LOC = -I$(top_srcdir)/storage/ndb/src/mgmapi
@ -43,3 +43,12 @@ libkernel.dsp: Makefile \
@$(top_srcdir)/storage/ndb/config/win-includes $@ $(INCLUDES) @$(top_srcdir)/storage/ndb/config/win-includes $@ $(INCLUDES)
@$(top_srcdir)/storage/ndb/config/win-sources $@ $(libkernel_a_SOURCES) @$(top_srcdir)/storage/ndb/config/win-sources $@ $(libkernel_a_SOURCES)
@$(top_srcdir)/storage/ndb/config/win-libraries $@ LIB $(LDADD) @$(top_srcdir)/storage/ndb/config/win-libraries $@ LIB $(LDADD)
EXTRA_PROGRAMS = ndbd_malloc_impl_test
ndbd_malloc_impl_test_CXXFLAGS = -DUNIT_TEST
ndbd_malloc_impl_test_SOURCES = ndbd_malloc_impl.cpp
ndbd_malloc_impl_test_LDFLAGS = @ndb_bin_am_ldflags@ \
$(top_builddir)/storage/ndb/src/libndbclient.la \
$(top_builddir)/mysys/libmysys.a \
$(top_builddir)/dbug/libdbug.a \
$(top_builddir)/strings/libmystrings.a

View File

@ -120,6 +120,19 @@ public:
head.firstItem = p.i; head.firstItem = p.i;
} }
/**
* Add a list to list
* @NOTE all elements _must_ be correctly initilized correctly wrt next/prev
*/
void add(Uint32 first, Ptr<T> & last);
/**
* Remove object from list
*
* @NOTE Does not return it to pool
*/
bool remove_front(Ptr<T> &);
Uint32 noOfElements() const { Uint32 noOfElements() const {
Uint32 c = 0; Uint32 c = 0;
Uint32 i = head.firstItem; Uint32 i = head.firstItem;
@ -246,6 +259,28 @@ SLList<T,U>::remove(){
head.firstItem = RNIL; head.firstItem = RNIL;
} }
template <class T, class U>
inline
bool
SLList<T,U>::remove_front(Ptr<T> & p){
p.i = head.firstItem;
if (p.i != RNIL)
{
p.p = thePool.getPtr(p.i);
head.firstItem = p.p->U::nextList;
return true;
}
return false;
}
template <class T, class U>
inline
void
SLList<T,U>::add(Uint32 first, Ptr<T> & last){
last.p->U::nextList = head.firstItem;
head.firstItem = first;
}
template <class T, class U> template <class T, class U>
inline inline
void void

View File

@ -0,0 +1,34 @@
Structure
Ndbd_mem_allocator
Handles allocation on 32k blocks
Provides Buddy allocation of max 8G objects
SuperPool 8k (chunk size 64k)
GroupPool - Metadata
DICT::RopePool
GroupPool - Disk operations
TUP::Page request
PGMAN::Page request
LGMAN::Log waiter
LGMAN::Log syncer
GroupPool - Disk space
Tsman::Datafile
Tsman::Tablespace
Lgman::Undofile
Lgman::Logfilegroup
TUP::Extent alloc info
SuperPool 32k
TUP Undo buffer
SUMA GCI buffer
Pgman::PageEntry
Direct Ndbd_mem_allocator
Pgman::GlobalPage -
TUP PageMan
Restore
Backup
Lgman::Logbuffer

Some files were not shown because too many files have changed in this diff Show More