Commit 3d6759d1 authored by sergefp@mysql.com's avatar sergefp@mysql.com

Merge 4.1->5.0

parents 9c51a97e 819db247
...@@ -37,8 +37,9 @@ static char *add_load_option(char *ptr,const char *object, ...@@ -37,8 +37,9 @@ static char *add_load_option(char *ptr,const char *object,
const char *statement); const char *statement);
static my_bool verbose=0,lock_tables=0,ignore_errors=0,opt_delete=0, static my_bool verbose=0,lock_tables=0,ignore_errors=0,opt_delete=0,
replace=0,silent=0,ignore=0,opt_compress=0,opt_local_file=0, replace=0,silent=0,ignore=0,opt_compress=0,
opt_low_priority= 0, tty_password= 0; opt_low_priority= 0, tty_password= 0;
static uint opt_local_file=0;
static MYSQL mysql_connection; static MYSQL mysql_connection;
static char *opt_password=0, *current_user=0, static char *opt_password=0, *current_user=0,
*current_host=0, *current_db=0, *fields_terminated=0, *current_host=0, *current_db=0, *fields_terminated=0,
......
drop table if exists t1,t2;
show tables; show tables;
Tables_in_mysql Tables_in_mysql
columns_priv columns_priv
...@@ -71,3 +72,8 @@ show tables; ...@@ -71,3 +72,8 @@ show tables;
Tables_in_test Tables_in_test
delete from mysql.user where user=_binary"test"; delete from mysql.user where user=_binary"test";
flush privileges; flush privileges;
create table t1 (id integer not null auto_increment primary key);
create temporary table t2(id integer not null auto_increment primary key);
set @id := 1;
delete from t1 where id like @id;
drop table t1;
...@@ -576,3 +576,23 @@ group_concat('x') ...@@ -576,3 +576,23 @@ group_concat('x')
NULL NULL
1 1
drop table t1; drop table t1;
CREATE TABLE t1 (id int, a varchar(9));
INSERT INTO t1 VALUES
(2, ''), (1, ''), (2, 'x'), (1, 'y'), (3, 'z'), (3, '');
SELECT GROUP_CONCAT(a) FROM t1;
GROUP_CONCAT(a)
,,x,y,z,
SELECT GROUP_CONCAT(a ORDER BY a) FROM t1;
GROUP_CONCAT(a ORDER BY a)
,,,x,y,z
SELECT GROUP_CONCAT(a) FROM t1 GROUP BY id;
GROUP_CONCAT(a)
,y
,x
z,
SELECT GROUP_CONCAT(a ORDER BY a) FROM t1 GROUP BY id;
GROUP_CONCAT(a ORDER BY a)
,y
,x
,z
DROP TABLE t1;
...@@ -758,6 +758,15 @@ select date(left(f1+0,8)) from t1 group by 1; ...@@ -758,6 +758,15 @@ select date(left(f1+0,8)) from t1 group by 1;
date(left(f1+0,8)) date(left(f1+0,8))
2005-06-06 2005-06-06
drop table t1; drop table t1;
create table t1(f1 varchar(5) key);
insert into t1 values (1),(2);
select sql_buffer_result max(f1) is null from t1;
max(f1) is null
0
select sql_buffer_result max(f1)+1 from t1;
max(f1)+1
3
drop table t1;
CREATE TABLE t1 (n int); CREATE TABLE t1 (n int);
INSERT INTO t1 VALUES (1); INSERT INTO t1 VALUES (1);
SELECT n+1 AS n FROM t1 GROUP BY n; SELECT n+1 AS n FROM t1 GROUP BY n;
......
...@@ -555,6 +555,19 @@ IFNULL(a, 'TEST') COALESCE(b, 'TEST') ...@@ -555,6 +555,19 @@ IFNULL(a, 'TEST') COALESCE(b, 'TEST')
4 TEST 4 TEST
TEST TEST TEST TEST
DROP TABLE t1,t2; DROP TABLE t1,t2;
DROP TABLE t1;
CREATE TABLE t1 (a int(11) NOT NULL);
INSERT INTO t1 VALUES (1),(2);
SELECT * FROM (SELECT a, a + 1, COUNT(*) FROM t1 GROUP BY a WITH ROLLUP) t;
a a + 1 COUNT(*)
1 2 1
2 3 1
NULL NULL 2
SELECT * FROM (SELECT a, LENGTH(a), COUNT(*) FROM t1 GROUP BY a WITH ROLLUP) t;
a LENGTH(a) COUNT(*)
1 1 1
2 1 1
NULL NULL 2
CREATE TABLE t1(id int, type char(1)); CREATE TABLE t1(id int, type char(1));
INSERT INTO t1 VALUES INSERT INTO t1 VALUES
(1,"A"),(2,"C"),(3,"A"),(4,"A"),(5,"B"), (1,"A"),(2,"C"),(3,"A"),(4,"A"),(5,"B"),
......
...@@ -6,6 +6,10 @@ ...@@ -6,6 +6,10 @@
# This test makes no sense with the embedded server # This test makes no sense with the embedded server
--source include/not_embedded.inc --source include/not_embedded.inc
--disable_warnings
drop table if exists t1,t2;
--enable_warnings
#connect (con1,localhost,root,,""); #connect (con1,localhost,root,,"");
#show tables; #show tables;
connect (con1,localhost,root,,mysql); connect (con1,localhost,root,,mysql);
...@@ -77,4 +81,18 @@ show tables; ...@@ -77,4 +81,18 @@ show tables;
delete from mysql.user where user=_binary"test"; delete from mysql.user where user=_binary"test";
flush privileges; flush privileges;
#
# Bug#12517: Clear user variables and replication events before
# closing temp tables in thread cleanup.
connect (con2,localhost,root,,test);
connection con2;
create table t1 (id integer not null auto_increment primary key);
create temporary table t2(id integer not null auto_increment primary key);
set @id := 1;
delete from t1 where id like @id;
disconnect con2;
--sleep 5
connection default;
drop table t1;
# End of 4.1 tests # End of 4.1 tests
...@@ -373,4 +373,20 @@ select * from (select group_concat(a) from t1) t2; ...@@ -373,4 +373,20 @@ select * from (select group_concat(a) from t1) t2;
select group_concat('x') UNION ALL select 1; select group_concat('x') UNION ALL select 1;
drop table t1; drop table t1;
#
# Bug #12863 : missing separators after first empty cancatanated elements
#
CREATE TABLE t1 (id int, a varchar(9));
INSERT INTO t1 VALUES
(2, ''), (1, ''), (2, 'x'), (1, 'y'), (3, 'z'), (3, '');
SELECT GROUP_CONCAT(a) FROM t1;
SELECT GROUP_CONCAT(a ORDER BY a) FROM t1;
SELECT GROUP_CONCAT(a) FROM t1 GROUP BY id;
SELECT GROUP_CONCAT(a ORDER BY a) FROM t1 GROUP BY id;
DROP TABLE t1;
# End of 4.1 tests # End of 4.1 tests
...@@ -575,6 +575,16 @@ CREATE TABLE t1 (id varchar(20) NOT NULL); ...@@ -575,6 +575,16 @@ CREATE TABLE t1 (id varchar(20) NOT NULL);
INSERT INTO t1 VALUES ('trans1'), ('trans2'); INSERT INTO t1 VALUES ('trans1'), ('trans2');
CREATE TABLE t2 (id varchar(20) NOT NULL, err_comment blob NOT NULL); CREATE TABLE t2 (id varchar(20) NOT NULL, err_comment blob NOT NULL);
INSERT INTO t2 VALUES ('trans1', 'a problem'); INSERT INTO t2 VALUES ('trans1', 'a problem');
#
# BUG#12695: Item_func_isnull::update_used_tables
# did not update const_item_cache
#
create table t1(f1 varchar(5) key);
insert into t1 values (1),(2);
select sql_buffer_result max(f1) is null from t1;
select sql_buffer_result max(f1)+1 from t1;
drop table t1;
SELECT COUNT(DISTINCT(t1.id)), LEFT(err_comment, 256) AS comment SELECT COUNT(DISTINCT(t1.id)), LEFT(err_comment, 256) AS comment
FROM t1 LEFT JOIN t2 ON t1.id=t2.id GROUP BY comment; FROM t1 LEFT JOIN t2 ON t1.id=t2.id GROUP BY comment;
......
...@@ -251,6 +251,19 @@ SELECT IFNULL(a, 'TEST'), COALESCE(b, 'TEST') FROM t2 ...@@ -251,6 +251,19 @@ SELECT IFNULL(a, 'TEST'), COALESCE(b, 'TEST') FROM t2
DROP TABLE t1,t2; DROP TABLE t1,t2;
# #
DROP TABLE t1;
#
# Bug #11885: derived table specified by a subquery with
# ROLLUP over expressions on not nullable group by attributes
#
CREATE TABLE t1 (a int(11) NOT NULL);
INSERT INTO t1 VALUES (1),(2);
SELECT * FROM (SELECT a, a + 1, COUNT(*) FROM t1 GROUP BY a WITH ROLLUP) t;
SELECT * FROM (SELECT a, LENGTH(a), COUNT(*) FROM t1 GROUP BY a WITH ROLLUP) t;
# Tests for bug #11639: ROLLUP over view executed through filesort # Tests for bug #11639: ROLLUP over view executed through filesort
# #
......
...@@ -33,7 +33,7 @@ class DefineBackupReq { ...@@ -33,7 +33,7 @@ class DefineBackupReq {
friend bool printDEFINE_BACKUP_REQ(FILE *, const Uint32 *, Uint32, Uint16); friend bool printDEFINE_BACKUP_REQ(FILE *, const Uint32 *, Uint32, Uint16);
public: public:
STATIC_CONST( SignalLength = 8 + NdbNodeBitmask::Size); STATIC_CONST( SignalLength = 9 + NdbNodeBitmask::Size);
private: private:
/** /**
...@@ -60,6 +60,13 @@ private: ...@@ -60,6 +60,13 @@ private:
* Length of backup data * Length of backup data
*/ */
Uint32 backupDataLen; Uint32 backupDataLen;
/**
* Backup flags
*/
/* & 0x3 - waitCompleted
*/
Uint32 flags;
}; };
class DefineBackupRef { class DefineBackupRef {
......
...@@ -36,11 +36,14 @@ class BackupReq { ...@@ -36,11 +36,14 @@ class BackupReq {
friend bool printBACKUP_REQ(FILE *, const Uint32 *, Uint32, Uint16); friend bool printBACKUP_REQ(FILE *, const Uint32 *, Uint32, Uint16);
public: public:
STATIC_CONST( SignalLength = 2 ); STATIC_CONST( SignalLength = 3 );
private: private:
Uint32 senderData; Uint32 senderData;
Uint32 backupDataLen; Uint32 backupDataLen;
/* & 0x3 - waitCompleted
*/
Uint32 flags;
}; };
class BackupData { class BackupData {
......
...@@ -30,28 +30,12 @@ ...@@ -30,28 +30,12 @@
* from the failed NDB node * from the failed NDB node
* *
*/ */
class NFCompleteRep { struct NFCompleteRep {
/**
* Sender(s)
*/
friend class Dbdict;
friend class Dblqh;
friend class Dbtc;
friend class Qmgr;
/**
* Sender/Reciver
*/
friend class Dbdih;
friend class ClusterMgr;
friend bool printNF_COMPLETE_REP(FILE *, const Uint32 *, Uint32, Uint16); friend bool printNF_COMPLETE_REP(FILE *, const Uint32 *, Uint32, Uint16);
public:
STATIC_CONST( SignalLength = 5 ); STATIC_CONST( SignalLength = 5 );
private:
/** /**
* Which block has completed... * Which block has completed...
* *
......
...@@ -24,34 +24,8 @@ ...@@ -24,34 +24,8 @@
* This signals is sent by Qmgr to NdbCntr * This signals is sent by Qmgr to NdbCntr
* and then from NdbCntr sent to: dih, dict, lqh, tc & API * and then from NdbCntr sent to: dih, dict, lqh, tc & API
*/ */
class NodeFailRep { struct NodeFailRep {
/**
* Sender(s)
*/
friend class Qmgr;
/**
* Sender(s) / Reciver(s)
*/
friend class Ndbcntr;
friend class Dbdict;
/**
* Reciver(s)
*/
friend class Dbdih;
friend class Dblqh;
friend class Dbtc;
friend class ClusterMgr;
friend class Trix;
friend class Backup;
friend class Suma;
friend class Grep;
friend class SafeCounterManager;
public:
STATIC_CONST( SignalLength = 3 + NodeBitmask::Size ); STATIC_CONST( SignalLength = 3 + NodeBitmask::Size );
private:
Uint32 failNo; Uint32 failNo;
......
...@@ -69,6 +69,9 @@ static const Uint32 BACKUP_SEQUENCE = 0x1F000000; ...@@ -69,6 +69,9 @@ static const Uint32 BACKUP_SEQUENCE = 0x1F000000;
static Uint32 g_TypeOfStart = NodeState::ST_ILLEGAL_TYPE; static Uint32 g_TypeOfStart = NodeState::ST_ILLEGAL_TYPE;
#define SEND_BACKUP_STARTED_FLAG(A) (((A) & 0x3) > 0)
#define SEND_BACKUP_COMPLETED_FLAG(A) (((A) & 0x3) > 1)
void void
Backup::execSTTOR(Signal* signal) Backup::execSTTOR(Signal* signal)
{ {
...@@ -852,23 +855,24 @@ Backup::execBACKUP_REQ(Signal* signal) ...@@ -852,23 +855,24 @@ Backup::execBACKUP_REQ(Signal* signal)
const Uint32 senderData = req->senderData; const Uint32 senderData = req->senderData;
const BlockReference senderRef = signal->senderBlockRef(); const BlockReference senderRef = signal->senderBlockRef();
const Uint32 dataLen32 = req->backupDataLen; // In 32 bit words const Uint32 dataLen32 = req->backupDataLen; // In 32 bit words
const Uint32 flags = signal->getLength() > 2 ? req->flags : 2;
if(getOwnNodeId() != getMasterNodeId()) { if(getOwnNodeId() != getMasterNodeId()) {
jam(); jam();
sendBackupRef(senderRef, signal, senderData, BackupRef::IAmNotMaster); sendBackupRef(senderRef, flags, signal, senderData, BackupRef::IAmNotMaster);
return; return;
}//if }//if
if (m_diskless) if (m_diskless)
{ {
sendBackupRef(senderRef, signal, senderData, sendBackupRef(senderRef, flags, signal, senderData,
BackupRef::CannotBackupDiskless); BackupRef::CannotBackupDiskless);
return; return;
} }
if(dataLen32 != 0) { if(dataLen32 != 0) {
jam(); jam();
sendBackupRef(senderRef, signal, senderData, sendBackupRef(senderRef, flags, signal, senderData,
BackupRef::BackupDefinitionNotImplemented); BackupRef::BackupDefinitionNotImplemented);
return; return;
}//if }//if
...@@ -883,7 +887,7 @@ Backup::execBACKUP_REQ(Signal* signal) ...@@ -883,7 +887,7 @@ Backup::execBACKUP_REQ(Signal* signal)
c_backups.seize(ptr); c_backups.seize(ptr);
if(ptr.i == RNIL) { if(ptr.i == RNIL) {
jam(); jam();
sendBackupRef(senderRef, signal, senderData, BackupRef::OutOfBackupRecord); sendBackupRef(senderRef, flags, signal, senderData, BackupRef::OutOfBackupRecord);
return; return;
}//if }//if
...@@ -894,6 +898,7 @@ Backup::execBACKUP_REQ(Signal* signal) ...@@ -894,6 +898,7 @@ Backup::execBACKUP_REQ(Signal* signal)
ptr.p->errorCode = 0; ptr.p->errorCode = 0;
ptr.p->clientRef = senderRef; ptr.p->clientRef = senderRef;
ptr.p->clientData = senderData; ptr.p->clientData = senderData;
ptr.p->flags = flags;
ptr.p->masterRef = reference(); ptr.p->masterRef = reference();
ptr.p->nodes = c_aliveNodes; ptr.p->nodes = c_aliveNodes;
ptr.p->backupId = 0; ptr.p->backupId = 0;
...@@ -931,20 +936,23 @@ void ...@@ -931,20 +936,23 @@ void
Backup::sendBackupRef(Signal* signal, BackupRecordPtr ptr, Uint32 errorCode) Backup::sendBackupRef(Signal* signal, BackupRecordPtr ptr, Uint32 errorCode)
{ {
jam(); jam();
sendBackupRef(ptr.p->clientRef, signal, ptr.p->clientData, errorCode); sendBackupRef(ptr.p->clientRef, ptr.p->flags, signal, ptr.p->clientData, errorCode);
cleanup(signal, ptr); cleanup(signal, ptr);
} }
void void
Backup::sendBackupRef(BlockReference senderRef, Signal *signal, Backup::sendBackupRef(BlockReference senderRef, Uint32 flags, Signal *signal,
Uint32 senderData, Uint32 errorCode) Uint32 senderData, Uint32 errorCode)
{ {
jam(); jam();
if (SEND_BACKUP_STARTED_FLAG(flags))
{
BackupRef* ref = (BackupRef*)signal->getDataPtrSend(); BackupRef* ref = (BackupRef*)signal->getDataPtrSend();
ref->senderData = senderData; ref->senderData = senderData;
ref->errorCode = errorCode; ref->errorCode = errorCode;
ref->masterRef = numberToRef(BACKUP, getMasterNodeId()); ref->masterRef = numberToRef(BACKUP, getMasterNodeId());
sendSignal(senderRef, GSN_BACKUP_REF, signal, BackupRef::SignalLength, JBB); sendSignal(senderRef, GSN_BACKUP_REF, signal, BackupRef::SignalLength, JBB);
}
if(errorCode != BackupRef::IAmNotMaster){ if(errorCode != BackupRef::IAmNotMaster){
signal->theData[0] = NDB_LE_BackupFailedToStart; signal->theData[0] = NDB_LE_BackupFailedToStart;
...@@ -1098,6 +1106,7 @@ Backup::sendDefineBackupReq(Signal *signal, BackupRecordPtr ptr) ...@@ -1098,6 +1106,7 @@ Backup::sendDefineBackupReq(Signal *signal, BackupRecordPtr ptr)
req->backupKey[1] = ptr.p->backupKey[1]; req->backupKey[1] = ptr.p->backupKey[1];
req->nodes = ptr.p->nodes; req->nodes = ptr.p->nodes;
req->backupDataLen = ptr.p->backupDataLen; req->backupDataLen = ptr.p->backupDataLen;
req->flags = ptr.p->flags;
ptr.p->masterData.gsn = GSN_DEFINE_BACKUP_REQ; ptr.p->masterData.gsn = GSN_DEFINE_BACKUP_REQ;
ptr.p->masterData.sendCounter = ptr.p->nodes; ptr.p->masterData.sendCounter = ptr.p->nodes;
...@@ -1193,12 +1202,17 @@ Backup::defineBackupReply(Signal* signal, BackupRecordPtr ptr, Uint32 nodeId) ...@@ -1193,12 +1202,17 @@ Backup::defineBackupReply(Signal* signal, BackupRecordPtr ptr, Uint32 nodeId)
/** /**
* Reply to client * Reply to client
*/ */
CRASH_INSERTION((10034));
if (SEND_BACKUP_STARTED_FLAG(ptr.p->flags))
{
BackupConf * conf = (BackupConf*)signal->getDataPtrSend(); BackupConf * conf = (BackupConf*)signal->getDataPtrSend();
conf->backupId = ptr.p->backupId; conf->backupId = ptr.p->backupId;
conf->senderData = ptr.p->clientData; conf->senderData = ptr.p->clientData;
conf->nodes = ptr.p->nodes; conf->nodes = ptr.p->nodes;
sendSignal(ptr.p->clientRef, GSN_BACKUP_CONF, signal, sendSignal(ptr.p->clientRef, GSN_BACKUP_CONF, signal,
BackupConf::SignalLength, JBB); BackupConf::SignalLength, JBB);
}
signal->theData[0] = NDB_LE_BackupStarted; signal->theData[0] = NDB_LE_BackupStarted;
signal->theData[1] = ptr.p->clientRef; signal->theData[1] = ptr.p->clientRef;
...@@ -2079,6 +2093,8 @@ Backup::stopBackupReply(Signal* signal, BackupRecordPtr ptr, Uint32 nodeId) ...@@ -2079,6 +2093,8 @@ Backup::stopBackupReply(Signal* signal, BackupRecordPtr ptr, Uint32 nodeId)
sendAbortBackupOrd(signal, ptr, AbortBackupOrd::BackupComplete); sendAbortBackupOrd(signal, ptr, AbortBackupOrd::BackupComplete);
if(!ptr.p->checkError()) if(!ptr.p->checkError())
{
if (SEND_BACKUP_COMPLETED_FLAG(ptr.p->flags))
{ {
BackupCompleteRep * rep = (BackupCompleteRep*)signal->getDataPtrSend(); BackupCompleteRep * rep = (BackupCompleteRep*)signal->getDataPtrSend();
rep->backupId = ptr.p->backupId; rep->backupId = ptr.p->backupId;
...@@ -2092,6 +2108,7 @@ Backup::stopBackupReply(Signal* signal, BackupRecordPtr ptr, Uint32 nodeId) ...@@ -2092,6 +2108,7 @@ Backup::stopBackupReply(Signal* signal, BackupRecordPtr ptr, Uint32 nodeId)
rep->nodes = ptr.p->nodes; rep->nodes = ptr.p->nodes;
sendSignal(ptr.p->clientRef, GSN_BACKUP_COMPLETE_REP, signal, sendSignal(ptr.p->clientRef, GSN_BACKUP_COMPLETE_REP, signal,
BackupCompleteRep::SignalLength, JBB); BackupCompleteRep::SignalLength, JBB);
}
signal->theData[0] = NDB_LE_BackupCompleted; signal->theData[0] = NDB_LE_BackupCompleted;
signal->theData[1] = ptr.p->clientRef; signal->theData[1] = ptr.p->clientRef;
...@@ -2129,13 +2146,15 @@ Backup::masterAbort(Signal* signal, BackupRecordPtr ptr) ...@@ -2129,13 +2146,15 @@ Backup::masterAbort(Signal* signal, BackupRecordPtr ptr)
return; return;
} }
if (SEND_BACKUP_COMPLETED_FLAG(ptr.p->flags))
{
BackupAbortRep* rep = (BackupAbortRep*)signal->getDataPtrSend(); BackupAbortRep* rep = (BackupAbortRep*)signal->getDataPtrSend();
rep->backupId = ptr.p->backupId; rep->backupId = ptr.p->backupId;
rep->senderData = ptr.p->clientData; rep->senderData = ptr.p->clientData;
rep->reason = ptr.p->errorCode; rep->reason = ptr.p->errorCode;
sendSignal(ptr.p->clientRef, GSN_BACKUP_ABORT_REP, signal, sendSignal(ptr.p->clientRef, GSN_BACKUP_ABORT_REP, signal,
BackupAbortRep::SignalLength, JBB); BackupAbortRep::SignalLength, JBB);
}
signal->theData[0] = NDB_LE_BackupAborted; signal->theData[0] = NDB_LE_BackupAborted;
signal->theData[1] = ptr.p->clientRef; signal->theData[1] = ptr.p->clientRef;
signal->theData[2] = ptr.p->backupId; signal->theData[2] = ptr.p->backupId;
...@@ -2267,6 +2286,13 @@ Backup::execDEFINE_BACKUP_REQ(Signal* signal) ...@@ -2267,6 +2286,13 @@ Backup::execDEFINE_BACKUP_REQ(Signal* signal)
ptr.p->errorCode = 0; ptr.p->errorCode = 0;
ptr.p->clientRef = req->clientRef; ptr.p->clientRef = req->clientRef;
ptr.p->clientData = req->clientData; ptr.p->clientData = req->clientData;
if(senderRef == reference())
ptr.p->flags = req->flags;
else
ptr.p->flags = req->flags & ~((Uint32)0x3); /* remove waitCompleted flags
* as non master should never
* reply
*/
ptr.p->masterRef = senderRef; ptr.p->masterRef = senderRef;
ptr.p->nodes = req->nodes; ptr.p->nodes = req->nodes;
ptr.p->backupId = backupId; ptr.p->backupId = backupId;
......
...@@ -412,6 +412,7 @@ public: ...@@ -412,6 +412,7 @@ public:
Uint32 clientRef; Uint32 clientRef;
Uint32 clientData; Uint32 clientData;
Uint32 flags;
Uint32 backupId; Uint32 backupId;
Uint32 backupKey[2]; Uint32 backupKey[2];
Uint32 masterRef; Uint32 masterRef;
...@@ -592,7 +593,7 @@ public: ...@@ -592,7 +593,7 @@ public:
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);
void sendBackupRef(BlockReference ref, Signal *signal, void sendBackupRef(BlockReference ref, Uint32 flags, Signal *signal,
Uint32 senderData, Uint32 errorCode); Uint32 senderData, Uint32 errorCode);
void dumpUsedResources(); void dumpUsedResources();
void cleanup(Signal*, BackupRecordPtr ptr); void cleanup(Signal*, BackupRecordPtr ptr);
......
...@@ -410,5 +410,5 @@ handler_sigusr1(int signum) ...@@ -410,5 +410,5 @@ handler_sigusr1(int signum)
failed_startups++; failed_startups++;
failed_startup_flag = true; failed_startup_flag = true;
} }
g_eventLogger.info("Received signal %d. Ndbd failed startup (%u).", signum, failed_startups); g_eventLogger.info("Angel received ndbd startup failure count %u.", failed_startups);
} }
...@@ -39,6 +39,8 @@ ...@@ -39,6 +39,8 @@
#include <signaldata/BackupSignalData.hpp> #include <signaldata/BackupSignalData.hpp>
#include <signaldata/GrepImpl.hpp> #include <signaldata/GrepImpl.hpp>
#include <signaldata/ManagementServer.hpp> #include <signaldata/ManagementServer.hpp>
#include <signaldata/NFCompleteRep.hpp>
#include <signaldata/NodeFailRep.hpp>
#include <NdbSleep.h> #include <NdbSleep.h>
#include <EventLogger.hpp> #include <EventLogger.hpp>
#include <DebuggerNames.hpp> #include <DebuggerNames.hpp>
...@@ -56,6 +58,8 @@ ...@@ -56,6 +58,8 @@
#include <mgmapi_config_parameters.h> #include <mgmapi_config_parameters.h>
#include <m_string.h> #include <m_string.h>
#include <SignalSender.hpp>
//#define MGM_SRV_DEBUG //#define MGM_SRV_DEBUG
#ifdef MGM_SRV_DEBUG #ifdef MGM_SRV_DEBUG
#define DEBUG(x) do ndbout << x << endl; while(0) #define DEBUG(x) do ndbout << x << endl; while(0)
...@@ -727,6 +731,15 @@ int MgmtSrvr::okToSendTo(NodeId processId, bool unCond) ...@@ -727,6 +731,15 @@ int MgmtSrvr::okToSendTo(NodeId processId, bool unCond)
} }
} }
void report_unknown_signal(SimpleSignal *signal)
{
g_eventLogger.error("Unknown signal received. SignalNumber: "
"%i from (%d, %x)",
signal->readSignalNumber(),
refToNode(signal->header.theSendersBlockRef),
refToBlock(signal->header.theSendersBlockRef));
}
/***************************************************************************** /*****************************************************************************
* Starting and stopping database nodes * Starting and stopping database nodes
****************************************************************************/ ****************************************************************************/
...@@ -1927,81 +1940,6 @@ MgmtSrvr::handleReceivedSignal(NdbApiSignal* signal) ...@@ -1927,81 +1940,6 @@ MgmtSrvr::handleReceivedSignal(NdbApiSignal* signal)
} }
break; break;
case GSN_BACKUP_CONF:{
const BackupConf * const conf =
CAST_CONSTPTR(BackupConf, signal->getDataPtr());
BackupEvent event;
event.Event = BackupEvent::BackupStarted;
event.Started.BackupId = conf->backupId;
event.Nodes = conf->nodes;
#ifdef VM_TRACE
ndbout_c("Backup master is %d", refToNode(signal->theSendersBlockRef));
#endif
backupCallback(event);
}
break;
case GSN_BACKUP_REF:{
const BackupRef * const ref =
CAST_CONSTPTR(BackupRef, signal->getDataPtr());
Uint32 errCode = ref->errorCode;
if(ref->errorCode == BackupRef::IAmNotMaster){
const Uint32 aNodeId = refToNode(ref->masterRef);
#ifdef VM_TRACE
ndbout_c("I'm not master resending to %d", aNodeId);
#endif
theWaitNode= aNodeId;
NdbApiSignal aSignal(_ownReference);
BackupReq* req = CAST_PTR(BackupReq, aSignal.getDataPtrSend());
aSignal.set(TestOrd::TraceAPI, BACKUP, GSN_BACKUP_REQ,
BackupReq::SignalLength);
req->senderData = 19;
req->backupDataLen = 0;
int i = theFacade->sendSignalUnCond(&aSignal, aNodeId);
if(i == 0){
return;
}
errCode = 5030;
}
BackupEvent event;
event.Event = BackupEvent::BackupFailedToStart;
event.FailedToStart.ErrorCode = errCode;
backupCallback(event);
break;
}
case GSN_BACKUP_ABORT_REP:{
const BackupAbortRep * const rep =
CAST_CONSTPTR(BackupAbortRep, signal->getDataPtr());
BackupEvent event;
event.Event = BackupEvent::BackupAborted;
event.Aborted.Reason = rep->reason;
event.Aborted.BackupId = rep->backupId;
event.Aborted.ErrorCode = rep->reason;
backupCallback(event);
}
break;
case GSN_BACKUP_COMPLETE_REP:{
const BackupCompleteRep * const rep =
CAST_CONSTPTR(BackupCompleteRep, signal->getDataPtr());
BackupEvent event;
event.Event = BackupEvent::BackupCompleted;
event.Completed.BackupId = rep->backupId;
event.Completed.NoOfBytes = rep->noOfBytes;
event.Completed.NoOfLogBytes = rep->noOfLogBytes;
event.Completed.NoOfRecords = rep->noOfRecords;
event.Completed.NoOfLogRecords = rep->noOfLogRecords;
event.Completed.stopGCP = rep->stopGCP;
event.Completed.startGCP = rep->startGCP;
event.Nodes = rep->nodes;
backupCallback(event);
}
break;
case GSN_MGM_LOCK_CONFIG_REP: case GSN_MGM_LOCK_CONFIG_REP:
case GSN_MGM_LOCK_CONFIG_REQ: case GSN_MGM_LOCK_CONFIG_REQ:
case GSN_MGM_UNLOCK_CONFIG_REP: case GSN_MGM_UNLOCK_CONFIG_REP:
...@@ -2466,6 +2404,9 @@ MgmtSrvr::eventReport(NodeId nodeId, const Uint32 * theData) ...@@ -2466,6 +2404,9 @@ MgmtSrvr::eventReport(NodeId nodeId, const Uint32 * theData)
int int
MgmtSrvr::startBackup(Uint32& backupId, int waitCompleted) MgmtSrvr::startBackup(Uint32& backupId, int waitCompleted)
{ {
SignalSender ss(theFacade);
ss.lock(); // lock will be released on exit
bool next; bool next;
NodeId nodeId = 0; NodeId nodeId = 0;
while((next = getNextNodeId(&nodeId, NDB_MGM_NODE_TYPE_NDB)) == true && while((next = getNextNodeId(&nodeId, NDB_MGM_NODE_TYPE_NDB)) == true &&
...@@ -2473,49 +2414,126 @@ MgmtSrvr::startBackup(Uint32& backupId, int waitCompleted) ...@@ -2473,49 +2414,126 @@ MgmtSrvr::startBackup(Uint32& backupId, int waitCompleted)
if(!next) return NO_CONTACT_WITH_DB_NODES; if(!next) return NO_CONTACT_WITH_DB_NODES;
NdbApiSignal* signal = getSignal(); SimpleSignal ssig;
if (signal == NULL) {
return COULD_NOT_ALLOCATE_MEMORY;
}
BackupReq* req = CAST_PTR(BackupReq, signal->getDataPtrSend()); BackupReq* req = CAST_PTR(BackupReq, ssig.getDataPtrSend());
signal->set(TestOrd::TraceAPI, BACKUP, GSN_BACKUP_REQ, ssig.set(ss, TestOrd::TraceAPI, BACKUP, GSN_BACKUP_REQ,
BackupReq::SignalLength); BackupReq::SignalLength);
req->senderData = 19; req->senderData = 19;
req->backupDataLen = 0; req->backupDataLen = 0;
assert(waitCompleted < 3);
req->flags = waitCompleted & 0x3;
int result; BackupEvent event;
if (waitCompleted == 2) { int do_send = 1;
result = sendRecSignal(nodeId, WAIT_BACKUP_COMPLETED, while (1) {
signal, true, 48*60*60*1000 /* 48 hours */); if (do_send)
} {
else if (waitCompleted == 1) { SendStatus result = ss.sendSignal(nodeId, &ssig);
result = sendRecSignal(nodeId, WAIT_BACKUP_STARTED, if (result != SEND_OK) {
signal, true, 5*60*1000 /*5 mins*/); return SEND_OR_RECEIVE_FAILED;
} }
else { if (waitCompleted == 0)
result = sendRecSignal(nodeId, NO_WAIT, signal, true); return 0;
do_send = 0;
} }
if (result == -1) { SimpleSignal *signal = ss.waitFor();
return SEND_OR_RECEIVE_FAILED;
int gsn = signal->readSignalNumber();
switch (gsn) {
case GSN_BACKUP_CONF:{
const BackupConf * const conf =
CAST_CONSTPTR(BackupConf, signal->getDataPtr());
event.Event = BackupEvent::BackupStarted;
event.Started.BackupId = conf->backupId;
event.Nodes = conf->nodes;
#ifdef VM_TRACE
ndbout_c("Backup(%d) master is %d", conf->backupId,
refToNode(signal->header.theSendersBlockRef));
#endif
backupId = conf->backupId;
if (waitCompleted == 1)
return 0;
// wait for next signal
break;
} }
case GSN_BACKUP_COMPLETE_REP:{
const BackupCompleteRep * const rep =
CAST_CONSTPTR(BackupCompleteRep, signal->getDataPtr());
#ifdef VM_TRACE
ndbout_c("Backup(%d) completed %d", rep->backupId);
#endif
event.Event = BackupEvent::BackupCompleted;
event.Completed.BackupId = rep->backupId;
event.Completed.NoOfBytes = rep->noOfBytes;
event.Completed.NoOfLogBytes = rep->noOfLogBytes;
event.Completed.NoOfRecords = rep->noOfRecords;
event.Completed.NoOfLogRecords = rep->noOfLogRecords;
event.Completed.stopGCP = rep->stopGCP;
event.Completed.startGCP = rep->startGCP;
event.Nodes = rep->nodes;
if (waitCompleted){ backupId = rep->backupId;
switch(m_lastBackupEvent.Event){ return 0;
case BackupEvent::BackupCompleted: }
backupId = m_lastBackupEvent.Completed.BackupId; case GSN_BACKUP_REF:{
const BackupRef * const ref =
CAST_CONSTPTR(BackupRef, signal->getDataPtr());
if(ref->errorCode == BackupRef::IAmNotMaster){
nodeId = refToNode(ref->masterRef);
#ifdef VM_TRACE
ndbout_c("I'm not master resending to %d", nodeId);
#endif
do_send = 1; // try again
continue;
}
event.Event = BackupEvent::BackupFailedToStart;
event.FailedToStart.ErrorCode = ref->errorCode;
return ref->errorCode;
}
case GSN_BACKUP_ABORT_REP:{
const BackupAbortRep * const rep =
CAST_CONSTPTR(BackupAbortRep, signal->getDataPtr());
event.Event = BackupEvent::BackupAborted;
event.Aborted.Reason = rep->reason;
event.Aborted.BackupId = rep->backupId;
event.Aborted.ErrorCode = rep->reason;
#ifdef VM_TRACE
ndbout_c("Backup %d aborted", rep->backupId);
#endif
return rep->reason;
}
case GSN_NF_COMPLETEREP:{
const NFCompleteRep * const rep =
CAST_CONSTPTR(NFCompleteRep, signal->getDataPtr());
#ifdef VM_TRACE
ndbout_c("Node %d fail completed", rep->failedNodeId);
#endif
if (rep->failedNodeId == nodeId ||
waitCompleted == 1)
return 1326;
// wait for next signal
// master node will report aborted backup
break; break;
case BackupEvent::BackupStarted: }
backupId = m_lastBackupEvent.Started.BackupId; case GSN_NODE_FAILREP:{
const NodeFailRep * const rep =
CAST_CONSTPTR(NodeFailRep, signal->getDataPtr());
#ifdef VM_TRACE
ndbout_c("Node %d failed", rep->failNo);
#endif
if (rep->failNo == nodeId ||
waitCompleted == 1)
return 1326;
// wait for next signal
// master node will report aborted backup
break; break;
case BackupEvent::BackupFailedToStart: }
return m_lastBackupEvent.FailedToStart.ErrorCode;
case BackupEvent::BackupAborted:
return m_lastBackupEvent.Aborted.ErrorCode;
default: default:
return -1; report_unknown_signal(signal);
break; return SEND_OR_RECEIVE_FAILED;
} }
} }
...@@ -2555,36 +2573,6 @@ MgmtSrvr::abortBackup(Uint32 backupId) ...@@ -2555,36 +2573,6 @@ MgmtSrvr::abortBackup(Uint32 backupId)
return 0; return 0;
} }
void
MgmtSrvr::backupCallback(BackupEvent & event)
{
DBUG_ENTER("MgmtSrvr::backupCallback");
m_lastBackupEvent = event;
switch(event.Event){
case BackupEvent::BackupFailedToStart:
DBUG_PRINT("info",("BackupEvent::BackupFailedToStart"));
theWaitState = NO_WAIT;
break;
case BackupEvent::BackupAborted:
DBUG_PRINT("info",("BackupEvent::BackupAborted"));
theWaitState = NO_WAIT;
break;
case BackupEvent::BackupCompleted:
DBUG_PRINT("info",("BackupEvent::BackupCompleted"));
theWaitState = NO_WAIT;
break;
case BackupEvent::BackupStarted:
if(theWaitState == WAIT_BACKUP_STARTED)
{
DBUG_PRINT("info",("BackupEvent::BackupStarted NO_WAIT"));
theWaitState = NO_WAIT;
} else {
DBUG_PRINT("info",("BackupEvent::BackupStarted"));
}
}
DBUG_VOID_RETURN;
}
/***************************************************************************** /*****************************************************************************
* Global Replication * Global Replication
......
...@@ -768,9 +768,6 @@ private: ...@@ -768,9 +768,6 @@ private:
static void *signalRecvThread_C(void *); static void *signalRecvThread_C(void *);
void signalRecvThreadRun(); void signalRecvThreadRun();
void backupCallback(BackupEvent &);
BackupEvent m_lastBackupEvent;
Config *_props; Config *_props;
int send(class NdbApiSignal* signal, Uint32 node, Uint32 node_type); int send(class NdbApiSignal* signal, Uint32 node, Uint32 node_type);
......
...@@ -34,7 +34,8 @@ libndbapi_la_SOURCES = \ ...@@ -34,7 +34,8 @@ libndbapi_la_SOURCES = \
NdbDictionaryImpl.cpp \ NdbDictionaryImpl.cpp \
DictCache.cpp \ DictCache.cpp \
ndb_cluster_connection.cpp \ ndb_cluster_connection.cpp \
NdbBlob.cpp NdbBlob.cpp \
SignalSender.cpp
INCLUDES_LOC = -I$(top_srcdir)/ndb/src/mgmapi INCLUDES_LOC = -I$(top_srcdir)/ndb/src/mgmapi
......
...@@ -264,6 +264,7 @@ NdbTransaction::execute(ExecType aTypeOfExec, ...@@ -264,6 +264,7 @@ NdbTransaction::execute(ExecType aTypeOfExec,
AbortOption abortOption, AbortOption abortOption,
int forceSend) int forceSend)
{ {
NdbError savedError= theError;
DBUG_ENTER("NdbTransaction::execute"); DBUG_ENTER("NdbTransaction::execute");
DBUG_PRINT("enter", ("aTypeOfExec: %d, abortOption: %d", DBUG_PRINT("enter", ("aTypeOfExec: %d, abortOption: %d",
aTypeOfExec, abortOption)); aTypeOfExec, abortOption));
...@@ -293,7 +294,11 @@ NdbTransaction::execute(ExecType aTypeOfExec, ...@@ -293,7 +294,11 @@ NdbTransaction::execute(ExecType aTypeOfExec,
NdbBlob* tBlob = tPrepOp->theBlobList; NdbBlob* tBlob = tPrepOp->theBlobList;
while (tBlob != NULL) { while (tBlob != NULL) {
if (tBlob->preExecute(tExecType, batch) == -1) if (tBlob->preExecute(tExecType, batch) == -1)
{
ret = -1; ret = -1;
if(savedError.code==0)
savedError= theError;
}
tBlob = tBlob->theNext; tBlob = tBlob->theNext;
} }
if (batch) { if (batch) {
...@@ -322,7 +327,11 @@ NdbTransaction::execute(ExecType aTypeOfExec, ...@@ -322,7 +327,11 @@ NdbTransaction::execute(ExecType aTypeOfExec,
NdbBlob* tBlob = tOp->theBlobList; NdbBlob* tBlob = tOp->theBlobList;
while (tBlob != NULL) { while (tBlob != NULL) {
if (tBlob->preCommit() == -1) if (tBlob->preCommit() == -1)
{
ret = -1; ret = -1;
if(savedError.code==0)
savedError= theError;
}
tBlob = tBlob->theNext; tBlob = tBlob->theNext;
} }
} }
...@@ -344,7 +353,12 @@ NdbTransaction::execute(ExecType aTypeOfExec, ...@@ -344,7 +353,12 @@ NdbTransaction::execute(ExecType aTypeOfExec,
} }
if (executeNoBlobs(tExecType, abortOption, forceSend) == -1) if (executeNoBlobs(tExecType, abortOption, forceSend) == -1)
{
ret = -1; ret = -1;
if(savedError.code==0)
savedError= theError;
}
#ifdef ndb_api_crash_on_complex_blob_abort #ifdef ndb_api_crash_on_complex_blob_abort
assert(theFirstOpInList == NULL && theLastOpInList == NULL); assert(theFirstOpInList == NULL && theLastOpInList == NULL);
#else #else
...@@ -359,7 +373,11 @@ NdbTransaction::execute(ExecType aTypeOfExec, ...@@ -359,7 +373,11 @@ NdbTransaction::execute(ExecType aTypeOfExec,
while (tBlob != NULL) { while (tBlob != NULL) {
// may add new operations if batch // may add new operations if batch
if (tBlob->postExecute(tExecType) == -1) if (tBlob->postExecute(tExecType) == -1)
{
ret = -1; ret = -1;
if(savedError.code==0)
savedError= theError;
}
tBlob = tBlob->theNext; tBlob = tBlob->theNext;
} }
} }
...@@ -390,6 +408,10 @@ NdbTransaction::execute(ExecType aTypeOfExec, ...@@ -390,6 +408,10 @@ NdbTransaction::execute(ExecType aTypeOfExec,
ndbout << "completed ops: " << n << endl; ndbout << "completed ops: " << n << endl;
} }
#endif #endif
if(savedError.code!=0 && theError.code==4350) // Trans already aborted
theError= savedError;
DBUG_RETURN(ret); DBUG_RETURN(ret);
} }
......
/* Copyright (C) 2003 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 */
#include "SignalSender.hpp"
#include <NdbSleep.h>
#include <SignalLoggerManager.hpp>
#include <signaldata/NFCompleteRep.hpp>
#include <signaldata/NodeFailRep.hpp>
SimpleSignal::SimpleSignal(bool dealloc){
memset(this, 0, sizeof(* this));
deallocSections = dealloc;
}
SimpleSignal::~SimpleSignal(){
if(!deallocSections)
return;
if(ptr[0].p != 0) delete []ptr[0].p;
if(ptr[1].p != 0) delete []ptr[1].p;
if(ptr[2].p != 0) delete []ptr[2].p;
}
void
SimpleSignal::set(class SignalSender& ss,
Uint8 trace, Uint16 recBlock, Uint16 gsn, Uint32 len){
header.theTrace = trace;
header.theReceiversBlockNumber = recBlock;
header.theVerId_signalNumber = gsn;
header.theLength = len;
header.theSendersBlockRef = refToBlock(ss.getOwnRef());
}
void
SimpleSignal::print(FILE * out){
fprintf(out, "---- Signal ----------------\n");
SignalLoggerManager::printSignalHeader(out, header, 0, 0, false);
SignalLoggerManager::printSignalData(out, header, theData);
for(Uint32 i = 0; i<header.m_noOfSections; i++){
Uint32 len = ptr[i].sz;
fprintf(out, " --- Section %d size=%d ---\n", i, len);
Uint32 * signalData = ptr[i].p;
while(len >= 7){
fprintf(out,
" H\'%.8x H\'%.8x H\'%.8x H\'%.8x H\'%.8x H\'%.8x H\'%.8x\n",
signalData[0], signalData[1], signalData[2], signalData[3],
signalData[4], signalData[5], signalData[6]);
len -= 7;
signalData += 7;
}
if(len > 0){
fprintf(out, " H\'%.8x", signalData[0]);
for(Uint32 i = 1; i<len; i++)
fprintf(out, " H\'%.8x", signalData[i]);
fprintf(out, "\n");
}
}
}
SignalSender::SignalSender(TransporterFacade *facade)
: m_lock(0)
{
m_cond = NdbCondition_Create();
theFacade = facade;
m_blockNo = theFacade->open(this, execSignal, execNodeStatus);
assert(m_blockNo > 0);
}
SignalSender::~SignalSender(){
int i;
if (m_lock)
unlock();
theFacade->close(m_blockNo,0);
// free these _after_ closing theFacade to ensure that
// we delete all signals
for (i= m_jobBuffer.size()-1; i>= 0; i--)
delete m_jobBuffer[i];
for (i= m_usedBuffer.size()-1; i>= 0; i--)
delete m_usedBuffer[i];
NdbCondition_Destroy(m_cond);
}
int SignalSender::lock()
{
if (NdbMutex_Lock(theFacade->theMutexPtr))
return -1;
m_lock= 1;
return 0;
}
int SignalSender::unlock()
{
if (NdbMutex_Unlock(theFacade->theMutexPtr))
return -1;
m_lock= 0;
return 0;
}
Uint32
SignalSender::getOwnRef() const {
return numberToRef(m_blockNo, theFacade->ownId());
}
Uint32
SignalSender::getAliveNode() const{
return theFacade->get_an_alive_node();
}
const ClusterMgr::Node &
SignalSender::getNodeInfo(Uint16 nodeId) const {
return theFacade->theClusterMgr->getNodeInfo(nodeId);
}
Uint32
SignalSender::getNoOfConnectedNodes() const {
return theFacade->theClusterMgr->getNoOfConnectedNodes();
}
SendStatus
SignalSender::sendSignal(Uint16 nodeId, const SimpleSignal * s){
return theFacade->theTransporterRegistry->prepareSend(&s->header,
1, // JBB
&s->theData[0],
nodeId,
&s->ptr[0]);
}
template<class T>
SimpleSignal *
SignalSender::waitFor(Uint32 timeOutMillis, T & t)
{
SimpleSignal * s = t.check(m_jobBuffer);
if(s != 0){
return s;
}
NDB_TICKS now = NdbTick_CurrentMillisecond();
NDB_TICKS stop = now + timeOutMillis;
Uint32 wait = (timeOutMillis == 0 ? 10 : timeOutMillis);
do {
NdbCondition_WaitTimeout(m_cond,
theFacade->theMutexPtr,
wait);
SimpleSignal * s = t.check(m_jobBuffer);
if(s != 0){
m_usedBuffer.push_back(s);
return s;
}
now = NdbTick_CurrentMillisecond();
wait = (timeOutMillis == 0 ? 10 : stop - now);
} while(stop > now || timeOutMillis == 0);
return 0;
}
class WaitForAny {
public:
SimpleSignal * check(Vector<SimpleSignal*> & m_jobBuffer){
if(m_jobBuffer.size() > 0){
SimpleSignal * s = m_jobBuffer[0];
m_jobBuffer.erase(0);
return s;
}
return 0;
}
};
SimpleSignal *
SignalSender::waitFor(Uint32 timeOutMillis){
WaitForAny w;
return waitFor(timeOutMillis, w);
}
class WaitForNode {
public:
Uint32 m_nodeId;
SimpleSignal * check(Vector<SimpleSignal*> & m_jobBuffer){
Uint32 len = m_jobBuffer.size();
for(Uint32 i = 0; i<len; i++){
if(refToNode(m_jobBuffer[i]->header.theSendersBlockRef) == m_nodeId){
SimpleSignal * s = m_jobBuffer[i];
m_jobBuffer.erase(i);
return s;
}
}
return 0;
}
};
SimpleSignal *
SignalSender::waitFor(Uint16 nodeId, Uint32 timeOutMillis){
WaitForNode w;
w.m_nodeId = nodeId;
return waitFor(timeOutMillis, w);
}
#include <NdbApiSignal.hpp>
void
SignalSender::execSignal(void* signalSender,
NdbApiSignal* signal,
class LinearSectionPtr ptr[3]){
SimpleSignal * s = new SimpleSignal(true);
s->header = * signal;
memcpy(&s->theData[0], signal->getDataPtr(), 4 * s->header.theLength);
for(Uint32 i = 0; i<s->header.m_noOfSections; i++){
s->ptr[i].p = new Uint32[ptr[i].sz];
s->ptr[i].sz = ptr[i].sz;
memcpy(s->ptr[i].p, ptr[i].p, 4 * ptr[i].sz);
}
SignalSender * ss = (SignalSender*)signalSender;
ss->m_jobBuffer.push_back(s);
NdbCondition_Signal(ss->m_cond);
}
void
SignalSender::execNodeStatus(void* signalSender,
Uint32 nodeId,
bool alive,
bool nfCompleted){
if (alive) {
// node connected
return;
}
SimpleSignal * s = new SimpleSignal(true);
SignalSender * ss = (SignalSender*)signalSender;
// node disconnected
if(nfCompleted)
{
// node shutdown complete
s->header.theVerId_signalNumber = GSN_NF_COMPLETEREP;
NFCompleteRep *rep = (NFCompleteRep *)s->getDataPtrSend();
rep->failedNodeId = nodeId;
}
else
{
// node failure
s->header.theVerId_signalNumber = GSN_NODE_FAILREP;
NodeFailRep *rep = (NodeFailRep *)s->getDataPtrSend();
rep->failNo = nodeId;
}
ss->m_jobBuffer.push_back(s);
NdbCondition_Signal(ss->m_cond);
}
template SimpleSignal* SignalSender::waitFor<WaitForNode>(unsigned, WaitForNode&);
template SimpleSignal* SignalSender::waitFor<WaitForAny>(unsigned, WaitForAny&);
template class Vector<SimpleSignal*>;
/* Copyright (C) 2003 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 */
#ifndef SIGNAL_SENDER_HPP
#define SIGNAL_SENDER_HPP
#include <ndb_global.h>
#include "TransporterFacade.hpp"
#include <Vector.hpp>
struct SimpleSignal {
public:
SimpleSignal(bool dealloc = false);
~SimpleSignal();
void set(class SignalSender&,
Uint8 trace, Uint16 recBlock, Uint16 gsn, Uint32 len);
struct SignalHeader header;
Uint32 theData[25];
LinearSectionPtr ptr[3];
int readSignalNumber() {return header.theVerId_signalNumber; }
Uint32 *getDataPtrSend() { return theData; }
const Uint32 *getDataPtr() const { return theData; }
void print(FILE * out = stdout);
private:
bool deallocSections;
};
class SignalSender {
public:
SignalSender(TransporterFacade *facade);
virtual ~SignalSender();
int lock();
int unlock();
Uint32 getOwnRef() const;
Uint32 getAliveNode() const;
const ClusterMgr::Node &getNodeInfo(Uint16 nodeId) const;
Uint32 getNoOfConnectedNodes() const;
SendStatus sendSignal(Uint16 nodeId, const SimpleSignal *);
SimpleSignal * waitFor(Uint32 timeOutMillis = 0);
SimpleSignal * waitFor(Uint16 nodeId, Uint32 timeOutMillis = 0);
SimpleSignal * waitFor(Uint16 nodeId, Uint16 gsn, Uint32 timeOutMillis = 0);
private:
int m_blockNo;
TransporterFacade * theFacade;
static void execSignal(void* signalSender,
NdbApiSignal* signal,
class LinearSectionPtr ptr[3]);
static void execNodeStatus(void* signalSender, Uint32 nodeId,
bool alive, bool nfCompleted);
int m_lock;
struct NdbCondition * m_cond;
Vector<SimpleSignal *> m_jobBuffer;
Vector<SimpleSignal *> m_usedBuffer;
template<class T>
SimpleSignal * waitFor(Uint32 timeOutMillis, T & t);
};
#endif
...@@ -50,14 +50,17 @@ NdbBackup::start(unsigned int & _backup_id){ ...@@ -50,14 +50,17 @@ NdbBackup::start(unsigned int & _backup_id){
2, // wait until completed 2, // wait until completed
&_backup_id, &_backup_id,
&reply) == -1) { &reply) == -1) {
g_err << "Could not start backup " << endl; g_err << "Error: " << ndb_mgm_get_latest_error(handle) << endl;
g_err << "Error: " << reply.message << endl; g_err << "Error msg: " << ndb_mgm_get_latest_error_msg(handle) << endl;
g_err << "Error desc: " << ndb_mgm_get_latest_error_desc(handle) << endl;
return -1; return -1;
} }
if(reply.return_code != 0){ if(reply.return_code != 0){
g_err << "PLEASE CHECK CODE NdbBackup.cpp line=" << __LINE__ << endl; g_err << "PLEASE CHECK CODE NdbBackup.cpp line=" << __LINE__ << endl;
g_err << "Error: " << reply.message << endl; g_err << "Error: " << ndb_mgm_get_latest_error(handle) << endl;
g_err << "Error msg: " << ndb_mgm_get_latest_error_msg(handle) << endl;
g_err << "Error desc: " << ndb_mgm_get_latest_error_desc(handle) << endl;
return reply.return_code; return reply.return_code;
} }
return 0; return 0;
......
...@@ -910,7 +910,7 @@ class Item_func_isnull :public Item_bool_func ...@@ -910,7 +910,7 @@ class Item_func_isnull :public Item_bool_func
else else
{ {
args[0]->update_used_tables(); args[0]->update_used_tables();
if (!(used_tables_cache=args[0]->used_tables())) if ((const_item_cache= !(used_tables_cache= args[0]->used_tables())))
{ {
/* Remember if the value is always NULL or never NULL */ /* Remember if the value is always NULL or never NULL */
cached_value= (longlong) args[0]->is_null(); cached_value= (longlong) args[0]->is_null();
......
...@@ -2740,7 +2740,9 @@ int dump_leaf_key(byte* key, element_count count __attribute__((unused)), ...@@ -2740,7 +2740,9 @@ int dump_leaf_key(byte* key, element_count count __attribute__((unused)),
String *result= &item->result; String *result= &item->result;
Item **arg= item->args, **arg_end= item->args + item->arg_count_field; Item **arg= item->args, **arg_end= item->args + item->arg_count_field;
if (result->length()) if (item->no_appended)
item->no_appended= FALSE;
else
result->append(*item->separator); result->append(*item->separator);
tmp.length(0); tmp.length(0);
...@@ -2925,6 +2927,7 @@ void Item_func_group_concat::clear() ...@@ -2925,6 +2927,7 @@ void Item_func_group_concat::clear()
result.copy(); result.copy();
null_value= TRUE; null_value= TRUE;
warning_for_row= FALSE; warning_for_row= FALSE;
no_appended= TRUE;
if (tree) if (tree)
reset_tree(tree); reset_tree(tree);
/* No need to reset the table as we never call write_row */ /* No need to reset the table as we never call write_row */
......
...@@ -898,6 +898,7 @@ class Item_func_group_concat : public Item_sum ...@@ -898,6 +898,7 @@ class Item_func_group_concat : public Item_sum
element_count count __attribute__((unused)), element_count count __attribute__((unused)),
Item_func_group_concat *group_concat_item); Item_func_group_concat *group_concat_item);
bool no_appended;
public: public:
Item_func_group_concat(Name_resolution_context *context_arg, Item_func_group_concat(Name_resolution_context *context_arg,
bool is_distinct, List<Item> *is_select, bool is_distinct, List<Item> *is_select,
......
...@@ -377,14 +377,14 @@ void THD::cleanup(void) ...@@ -377,14 +377,14 @@ void THD::cleanup(void)
mysql_ha_flush(this, (TABLE_LIST*) 0, mysql_ha_flush(this, (TABLE_LIST*) 0,
MYSQL_HA_CLOSE_FINAL | MYSQL_HA_FLUSH_ALL); MYSQL_HA_CLOSE_FINAL | MYSQL_HA_FLUSH_ALL);
hash_free(&handler_tables_hash); hash_free(&handler_tables_hash);
delete_dynamic(&user_var_events);
hash_free(&user_vars);
close_temporary_tables(this); close_temporary_tables(this);
my_free((char*) variables.time_format, MYF(MY_ALLOW_ZERO_PTR)); my_free((char*) variables.time_format, MYF(MY_ALLOW_ZERO_PTR));
my_free((char*) variables.date_format, MYF(MY_ALLOW_ZERO_PTR)); my_free((char*) variables.date_format, MYF(MY_ALLOW_ZERO_PTR));
my_free((char*) variables.datetime_format, MYF(MY_ALLOW_ZERO_PTR)); my_free((char*) variables.datetime_format, MYF(MY_ALLOW_ZERO_PTR));
delete_dynamic(&user_var_events);
hash_free(&user_vars);
sp_cache_clear(&sp_proc_cache); sp_cache_clear(&sp_proc_cache);
sp_cache_clear(&sp_func_cache); sp_cache_clear(&sp_func_cache); /*psergey: move to ~THD? */
if (global_read_lock) if (global_read_lock)
unlock_global_read_lock(this); unlock_global_read_lock(this);
if (ull) if (ull)
......
...@@ -13043,6 +13043,8 @@ void free_underlaid_joins(THD *thd, SELECT_LEX *select) ...@@ -13043,6 +13043,8 @@ void free_underlaid_joins(THD *thd, SELECT_LEX *select)
The function replaces occurrences of group by fields in expr The function replaces occurrences of group by fields in expr
by ref objects for these fields unless they are under aggregate by ref objects for these fields unless they are under aggregate
functions. functions.
The function also corrects value of the the maybe_null attribute
for the items of all subexpressions containing group by fields.
IMPLEMENTATION IMPLEMENTATION
The function recursively traverses the tree of the expr expression, The function recursively traverses the tree of the expr expression,
...@@ -13053,6 +13055,9 @@ void free_underlaid_joins(THD *thd, SELECT_LEX *select) ...@@ -13053,6 +13055,9 @@ void free_underlaid_joins(THD *thd, SELECT_LEX *select)
This substitution is needed GROUP BY queries with ROLLUP if This substitution is needed GROUP BY queries with ROLLUP if
SELECT list contains expressions over group by attributes. SELECT list contains expressions over group by attributes.
TODO: Some functions are not null-preserving. For those functions
updating of the maybe_null attribute is an overkill.
EXAMPLES EXAMPLES
SELECT a+1 FROM t1 GROUP BY a WITH ROLLUP SELECT a+1 FROM t1 GROUP BY a WITH ROLLUP
SELECT SUM(a)+a FROM t1 GROUP BY a WITH ROLLUP SELECT SUM(a)+a FROM t1 GROUP BY a WITH ROLLUP
...@@ -13074,6 +13079,7 @@ static bool change_group_ref(THD *thd, Item_func *expr, ORDER *group_list, ...@@ -13074,6 +13079,7 @@ static bool change_group_ref(THD *thd, Item_func *expr, ORDER *group_list,
arg != arg_end; arg++) arg != arg_end; arg++)
{ {
Item *item= *arg; Item *item= *arg;
bool arg_changed= FALSE;
if (item->type() == Item::FIELD_ITEM || item->type() == Item::REF_ITEM) if (item->type() == Item::FIELD_ITEM || item->type() == Item::REF_ITEM)
{ {
ORDER *group_tmp; ORDER *group_tmp;
...@@ -13086,15 +13092,20 @@ static bool change_group_ref(THD *thd, Item_func *expr, ORDER *group_list, ...@@ -13086,15 +13092,20 @@ static bool change_group_ref(THD *thd, Item_func *expr, ORDER *group_list,
item->name))) item->name)))
return 1; // fatal_error is set return 1; // fatal_error is set
thd->change_item_tree(arg, new_item); thd->change_item_tree(arg, new_item);
*changed= TRUE; arg_changed= TRUE;
} }
} }
} }
else if (item->type() == Item::FUNC_ITEM) else if (item->type() == Item::FUNC_ITEM)
{ {
if (change_group_ref(thd, (Item_func *) item, group_list, changed)) if (change_group_ref(thd, (Item_func *) item, group_list, &arg_changed))
return 1; return 1;
} }
if (arg_changed)
{
expr->maybe_null= 1;
*changed= TRUE;
}
} }
} }
return 0; return 0;
...@@ -13157,7 +13168,7 @@ bool JOIN::rollup_init() ...@@ -13157,7 +13168,7 @@ bool JOIN::rollup_init()
} }
if (item->type() == Item::FUNC_ITEM) if (item->type() == Item::FUNC_ITEM)
{ {
bool changed= 0; bool changed= FALSE;
if (change_group_ref(thd, (Item_func *) item, group_list, &changed)) if (change_group_ref(thd, (Item_func *) item, group_list, &changed))
return 1; return 1;
/* /*
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment