Below is the list of changes that have just been committed into a local
5.1 repository of dli. When dli does a push these changes will
be propagated to the main repository and, within 24 hours after the
push, to the public repository.
For information on how to access the public repository
see http://dev.mysql.com/doc/mysql/en/installing-source-tree.html
ChangeSet@stripped, 2007-05-09 10:19:29+08:00, dli@stripped +36 -0
WL#3615 NDB: Endian Incompatability Support.
The long term goal is to mix SPARC 32 & 64-bit, PPC and x86 32 & 64-bit architetures for any node in a cluster.
The phase I, or the minimum requirement, is to develop and test under the following configuration required by some special customers:
- 32-bit API running on either 32/64 bit Solaris/SPARC
&
- 64-bit Data Nodes on 64-bit Solaris/SPARC
or
- 64-bit Data Nodes with x86 (AMD Opteron, or Intel chips)
This changeset is for the phase I target.
storage/ndb/config/type_util.mk.am@stripped, 2007-05-09 10:19:25+08:00, dli@stripped +2 -1
WL#3615 NDB: Endian Incompatability Support.
Added include/kernel into including directory, so that can use DictTabInfo in SimplePropertites.cpp.
storage/ndb/include/kernel/GlobalSignalNumbers.h@stripped, 2007-05-09 10:19:25+08:00, dli@stripped +1 -1
WL#3615 NDB: Endian Incompatability Support.
Added a new signal GSN_TUP_ORIG_ATTRINFO to handle REDO log.
storage/ndb/include/kernel/NodeInfo.hpp@stripped, 2007-05-09 10:19:25+08:00, dli@stripped +6 -2
WL#3615 NDB: Endian Incompatability Support.
Added a variable member for class NodeInfo to store the endian of the node.
storage/ndb/include/kernel/signaldata/ApiRegSignalData.hpp@stripped, 2007-05-09 10:19:25+08:00, dli@stripped +4 -2
WL#3615 NDB: Endian Incompatability Support.
Added a variable member for class ApiRegReq to store endian of node, so that we can transfer the endian of node in ApiRegReq signal.
storage/ndb/include/kernel/signaldata/CmRegSignalData.hpp@stripped, 2007-05-09 10:19:25+08:00, dli@stripped +4 -2
WL#3615 NDB: Endian Incompatability Support.
Added a variable member for class CmNodeInfoReq to store the endian of NDB node, so that we can transfer the endian of NDB node in signal CmNodeInfoReq.
storage/ndb/include/kernel/signaldata/TupCommit.hpp@stripped, 2007-05-09 10:19:25+08:00, dli@stripped +2 -1
WL#3615 NDB: Endian Incompatability Support.
Added a variable member for class TupCommitReq to store the reference of API node.
storage/ndb/include/kernel/signaldata/TuxBound.hpp@stripped, 2007-05-09 10:19:25+08:00, dli@stripped +5 -1
WL#3615 NDB: Endian Incompatability Support.
Added a variable member for class TuxBoundInfo to store the block reference of scanning API node, so that we can handle endian for range scan.
storage/ndb/include/util/SimpleProperties.hpp@stripped, 2007-05-09 10:19:25+08:00, dli@stripped +75 -6
WL#3615 NDB: Endian Incompatability Support.
Fixed to handle endian for table related operations.
For table related operations, the table information gotten from the API node will be handled in SimpleProperties.cpp, so handle endian for table related operations here concentratively.
storage/ndb/include/util/ndb_endian.h@stripped, 2007-05-09 10:19:26+08:00, dli@stripped +43 -0
BitKeeper file /home/dli/mysql/mysql-5.1/mysql-5.1-wl-3615/storage/ndb/include/util/ndb_endian.h
storage/ndb/include/util/ndb_endian.h@stripped, 2007-05-09 10:19:26+08:00, dli@stripped +0 -0
storage/ndb/src/common/debugger/signaldata/SignalNames.cpp@stripped, 2007-05-09 10:19:25+08:00, dli@stripped +1 -0
WL#3615 NDB: Endian Incompatability Support.
Added alias signal name for newly added signal GSN_TUP_ORIG_ATTRINFO.
storage/ndb/src/common/transporter/Packer.cpp@stripped, 2007-05-09 10:19:25+08:00, dli@stripped +57 -18
WL#3615 NDB: Endian Incompatability Support.
All the signals received from other blocks will be unpacked here firstly. We compare the endian of sender node and own node here, if they are different, swap the byte-order of all the signal data.
storage/ndb/src/common/util/Makefile.am@stripped, 2007-05-09 10:19:25+08:00, dli@stripped +1 -1
WL#3615 NDB: Endian Incompatability Support.
Added newly added file ndb_endian.c into Makefile.am in order to build it.
storage/ndb/src/common/util/SimpleProperties.cpp@stripped, 2007-05-09 10:19:25+08:00, dli@stripped +243 -10
WL#3615 NDB: Endian Incompatability Support.
Fixed to handle endian for table related operations.
For table related operations, the table information gotten from the API node will be handled in SimpleProperties.cpp, so handle endian for table related operations here concentratively.
storage/ndb/src/common/util/ndb_endian.c@stripped, 2007-05-09 10:19:26+08:00, dli@stripped +155 -0
BitKeeper file /home/dli/mysql/mysql-5.1/mysql-5.1-wl-3615/storage/ndb/src/common/util/ndb_endian.c
storage/ndb/src/common/util/ndb_endian.c@stripped, 2007-05-09 10:19:26+08:00, dli@stripped +0 -0
storage/ndb/src/kernel/blocks/cmvmi/Cmvmi.cpp@stripped, 2007-05-09 10:19:25+08:00, dli@stripped +38 -0
WL#3615 NDB: Endian Incompatability Support.
Handle endian for event info here.
storage/ndb/src/kernel/blocks/dbacc/DbaccMain.cpp@stripped, 2007-05-09 10:19:25+08:00, dli@stripped +5 -0
WL#3615 NDB: Endian Incompatability Support.
Handle endian for reading table primary key in DBACC block.
storage/ndb/src/kernel/blocks/dbdict/Dbdict.cpp@stripped, 2007-05-09 10:19:25+08:00, dli@stripped +228 -25
WL#3615 NDB: Endian Incompatability Support.
Handle endian for all the table related operations.
storage/ndb/src/kernel/blocks/dblqh/Dblqh.hpp@stripped, 2007-05-09 10:19:25+08:00, dli@stripped +20 -0
WL#3615 NDB: Endian Incompatability Support.
Added new variable and function member for DBLQH block.
storage/ndb/src/kernel/blocks/dblqh/DblqhInit.cpp@stripped, 2007-05-09 10:19:25+08:00, dli@stripped +1 -0
WL#3615 NDB: Endian Incompatability Support.
Fixed for newly added signal GSN_TUP_ORIG_ATTRINFO.
storage/ndb/src/kernel/blocks/dblqh/DblqhMain.cpp@stripped, 2007-05-09 10:19:25+08:00, dli@stripped +325 -22
WL#3615 NDB: Endian Incompatability Support.
Fixed for handling endian in DBLQH block, in DBLQH block will handle endian for the following operations:
- key info
- attribute info
- redo-log
storage/ndb/src/kernel/blocks/dbtc/Dbtc.hpp@stripped, 2007-05-09 10:19:26+08:00, dli@stripped +3 -0
WL#3615 NDB: Endian Incompatability Support.
Added new functions for handling key info in DBTC.
storage/ndb/src/kernel/blocks/dbtc/DbtcMain.cpp@stripped, 2007-05-09 10:19:26+08:00, dli@stripped +171 -1
WL#3615 NDB: Endian Incompatability Support.
Handle endian for key info in DBTC.
storage/ndb/src/kernel/blocks/dbtup/Dbtup.hpp@stripped, 2007-05-09 10:19:26+08:00, dli@stripped +10 -0
WL#3615 NDB: Endian Incompatability Support.
Added variable and function member for handling endian in DBTUP block.
storage/ndb/src/kernel/blocks/dbtup/DbtupCommit.cpp@stripped, 2007-05-09 10:19:26+08:00, dli@stripped +3 -0
WL#3615 NDB: Endian Incompatability Support.
Set req_struct.rec_blockref for TUP_COMMITREQ signal.
storage/ndb/src/kernel/blocks/dbtup/DbtupExecQuery.cpp@stripped, 2007-05-09 10:19:26+08:00, dli@stripped +119 -0
WL#3615 NDB: Endian Incompatability Support.
Handle endian for attrinfo here, so that can write correct attrinfo into redo-log.
storage/ndb/src/kernel/blocks/dbtup/DbtupGen.cpp@stripped, 2007-05-09 10:19:26+08:00, dli@stripped +1 -0
WL#3615 NDB: Endian Incompatability Support.
Initialize the new variable member in constructor.
storage/ndb/src/kernel/blocks/dbtup/DbtupIndex.cpp@stripped, 2007-05-09 10:19:26+08:00, dli@stripped +9 -0
WL#3615 NDB: Endian Incompatability Support.
Set req_struct.rec_blockref here, so that can use it while reading attributes.
storage/ndb/src/kernel/blocks/dbtup/DbtupRoutines.cpp@stripped, 2007-05-09 10:19:26+08:00, dli@stripped +428 -10
WL#3615 NDB: Endian Incompatability Support.
Handle endian for all the attribute related operations.
All the attribute related operations will be handled here, so we handle the endian for attributes here concentratively, not all the data types need to be handled for endian, for each attribute we should judge whether it need to be handled for endian. We compare the endian of the API node and own node here, if they are different then we should handle the endian of the attribute. And the API block reference is transfered in req_struct->rec_blockref.
storage/ndb/src/kernel/blocks/dbtup/DbtupTrigger.cpp@stripped, 2007-05-09 10:19:26+08:00, dli@stripped +11 -0
WL#3615 NDB: Endian Incompatability Support.
Set req_struct->rec_blockref to DBTC block reference if the attribute info receiver is DBTC block in executeTrigger() function.
storage/ndb/src/kernel/blocks/dbtux/DbtuxScan.cpp@stripped, 2007-05-09 10:19:26+08:00, dli@stripped +24 -1
WL#3615 NDB: Endian Incompatability Support.
Handled endian for range scan operation here.
For range scan, we should handle the endian for BOUND_INFO.
storage/ndb/src/kernel/blocks/qmgr/QmgrMain.cpp@stripped, 2007-05-09 10:19:26+08:00, dli@stripped +34 -0
WL#3615 NDB: Endian Incompatability Support.
Get the endian info of API node from API_REGREQ signal, set own node into API_REGCONF signal and send to API node.
Get the endian info of other DB nodes from CM_NODEINFOREQ signal, set own node into CM_NODEINFOREQ signal or CM_NODEINFOCONF signal to send to other DB nodes.
Also handle endian for API_VERSION signal.
storage/ndb/src/kernel/vm/SimplePropertiesSection.cpp@stripped, 2007-05-09 10:19:26+08:00, dli@stripped +120 -2
WL#3615 NDB: Endian Incompatability Support.
Handle endian for table related operations.
For table reated operations, some operation need to read/write table information from/to section buffer here, so handle endian for these operations here.
storage/ndb/src/kernel/vm/SimulatedBlock.cpp@stripped, 2007-05-09 10:19:26+08:00, dli@stripped +439 -0
WL#3615 NDB: Endian Incompatability Support.
Added function to compare edian here.
Added function to handle endian for key attributes here.
Added here in order to use it in all blocks.
storage/ndb/src/kernel/vm/SimulatedBlock.hpp@stripped, 2007-05-09 10:19:26+08:00, dli@stripped +21 -2
WL#3615 NDB: Endian Incompatability Support.
Declare the new added functions in SimulatedBlock.cpp.
storage/ndb/src/mgmsrv/Services.cpp@stripped, 2007-05-09 10:19:26+08:00, dli@stripped +0 -10
WL#3615 NDB: Endian Incompatability Support.
Removed the endian compatability judgement of connecting node with management server, to allow the node with endianness different from the management server to connect to the management server.
storage/ndb/src/ndbapi/ClusterMgr.cpp@stripped, 2007-05-09 10:19:26+08:00, dli@stripped +22 -0
WL#3615 NDB: Endian Incompatability Support.
Set endian info of API node into API_REGREQ signal and send to DB nodes.
# This is a BitKeeper patch. What follows are the unified diffs for the
# set of deltas contained in the patch. The rest of the patch, the part
# that BitKeeper cares about, is below these diffs.
# User: dli
# Host: dev3-164.dev.cn.tlan
# Root: /home/dli/mysql/mysql-5.1/mysql-5.1-wl-3615
--- New file ---
+++ storage/ndb/include/util/ndb_endian.h 07/05/09 10:19:26
/* Copyright (C) 2007 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 NDB_ENDIAN_H
#define NDB_ENDIAN_H
#include <ndb_types.h>
#define NDB_LITTLE_ENDIAN 0
#define NDB_BIG_ENDIAN 1
#ifdef __cplusplus
extern "C" {
#endif
Uint32 ndbCheckEndian();
Uint32 ndbSwapOneWord32(Uint32 data);
void ndbSwapManyWords32(Uint32 *data, Uint32 length);
Uint16 ndbSwapOneWord16(Uint16 data);
void ndbSwapManyWords16(Uint32 *data, Uint32 length);
void ndbSwapManyWords64(Uint32 *data, Uint32 length);
#ifdef __cplusplus
}
#endif
#endif
--- New file ---
+++ storage/ndb/src/common/util/ndb_endian.c 07/05/09 10:19:26
/* Copyright (C) 2007 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 <ndb_global.h>
#include <ndb_endian.h>
#include <NdbOut.hpp>
/**
* Check the endian of own node.
*/
Uint32 ndbCheckEndian()
{
union
{
long l;
char c[sizeof(long)];
} endian_check;
endian_check.l = 1;
return ((endian_check.c[sizeof(long)-1]) ? NDB_BIG_ENDIAN : NDB_LITTLE_ENDIAN);
}
/**
* Swap the byte order of one 32-bit word.
*
* Parameters:
* data: the data to be swapped
*
* Returned value:
* the data after swapped.
*/
Uint32 ndbSwapOneWord32(Uint32 data)
{
Uint32 data2;
((unsigned char*)&data2)[0] = ((unsigned char*)&data)[3];
((unsigned char*)&data2)[1] = ((unsigned char*)&data)[2];
((unsigned char*)&data2)[2] = ((unsigned char*)&data)[1];
((unsigned char*)&data2)[3] = ((unsigned char*)&data)[0];
return data2;
}
/**
* Swap the byte order of many 32-bit words.
*
* Parameters:
* data: the data to be swapped
* length: the number of 32-bit words
*
* Returned value:
* the value after swapped is stored in data.
*/
void ndbSwapManyWords32(Uint32 *data, Uint32 length)
{
Uint32 data2;
do {
data2 = ndbSwapOneWord32(*data);
*data = data2;
data++;
} while (--length);
}
/**
* Swap the byte order of one 16-bit word.
*
* Parameters:
* data: the data to be swapped
*
* Returned value:
* the data after swapped.
*/
Uint16 ndbSwapOneWord16(Uint16 data)
{
Uint16 data2;
((unsigned char*)&data2)[0] = ((unsigned char*)&data)[1];
((unsigned char*)&data2)[1] = ((unsigned char*)&data)[0];
return data2;
}
/**
* Swap the byte order for 16-bit words.
* If the endian of the sender and receiver are different,
* the byte order of all the data in signal will be swapped
* for each 32-bit word.
* So for 16-bit word, we can just exchange the high and
* low 16-bit of the 32-bit word.
*
* Parameters:
* data: the data to be swapped
* length: the number of 32-bit words
*
* Returned value:
* the value after swapped is stored in data.
*/
void ndbSwapManyWords16(Uint32 *data, Uint32 length)
{
Uint32 data2;
do {
data2 = (((*data) & 0xFFFF0000) >> 16) + (((*data) & 0x0000FFFF) << 16);
*data = data2;
data++;
} while (--length);
}
/**
* Swap the byte order for 64-bit words.
* If the endian of the sender and receiver are different,
* the byte order of all the data in signal will be swapped
* for each 32-bit word.
* So for 64-bit word, we can just exchange its high and
* low 32-bit words.
*
* Note:
* On Solaris Sparc, if transfer a Uint32 type address to
* a Uint64 type address, may cause Bus Error.
*
* Parameters:
* data: the data to be swapped
* length: the number of 32-bit words
*
* Returned value:
* the value after swapped is stored in data.
*/
void ndbSwapManyWords64(Uint32 *data, Uint32 length)
{
Uint32 data2;
do {
data2 = *data;
*data = *(data + 1);
*(data + 1) = data2;
data += 2;
length -= 2;
} while (length);
}
--- 1.29/storage/ndb/include/kernel/GlobalSignalNumbers.h 2007-05-09 10:19:39 +08:00
+++ 1.30/storage/ndb/include/kernel/GlobalSignalNumbers.h 2007-05-09 10:19:39 +08:00
@@ -524,8 +524,8 @@ extern const GlobalSignalNumber NO_OF_SI
#define GSN_TUP_ADD_ATTRREQ 417
#define GSN_TUP_ATTRINFO 418
#define GSN_TUP_COMMITREQ 419
+#define GSN_TUP_ORIG_ATTRINFO 421
-/* 421 unused */
/* 422 unused */
/* 423 unused */
--- 1.5/storage/ndb/include/kernel/NodeInfo.hpp 2007-05-09 10:19:39 +08:00
+++ 1.6/storage/ndb/include/kernel/NodeInfo.hpp 2007-05-09 10:19:39 +08:00
@@ -19,6 +19,7 @@
#include <NdbOut.hpp>
#include <mgmapi_config_parameters.h>
+#include <ndb_endian.h>
class NodeInfo {
public:
@@ -34,10 +35,11 @@ public:
INVALID = 255 ///< Invalid type
};
NodeType getType() const;
-
+
Uint32 m_version; ///< Node version
Uint32 m_signalVersion; ///< Signal version
Uint32 m_type; ///< Node type
+ Uint32 m_endian; ///< Node endian type
Uint32 m_connectCount; ///< No of times connected
bool m_connected; ///< Node is connected
Uint32 m_heartbeat_cnt; ///< Missed heartbeats
@@ -51,6 +53,7 @@ NodeInfo::NodeInfo(){
m_version = 0;
m_signalVersion = 0;
m_type = INVALID;
+ m_endian = NDB_LITTLE_ENDIAN; //default is little-endian
m_connectCount = 0;
m_heartbeat_cnt= 0;
}
@@ -84,7 +87,8 @@ operator<<(NdbOut& ndbout, const NodeInf
}
ndbout << " version: " << info.m_version
- << " sig. version; " << info.m_signalVersion
+ << " sig. version: " << info.m_signalVersion
+ << " endian: " << info.m_endian
<< " connect count: " << info.m_connectCount
<< "]";
return ndbout;
--- 1.4/storage/ndb/include/kernel/signaldata/ApiRegSignalData.hpp 2007-05-09 10:19:39 +08:00
+++ 1.5/storage/ndb/include/kernel/signaldata/ApiRegSignalData.hpp 2007-05-09 10:19:39 +08:00
@@ -31,11 +31,12 @@ class ApiRegReq {
friend class Qmgr;
public:
- STATIC_CONST( SignalLength = 2 );
+ STATIC_CONST( SignalLength = 3 );
private:
Uint32 ref;
Uint32 version; // Version of API node
+ Uint32 endian; // Endian of API node
};
/**
@@ -80,13 +81,14 @@ class ApiRegConf {
friend class ClusterMgr;
public:
- STATIC_CONST( SignalLength = 3 + NodeState::DataLength );
+ STATIC_CONST( SignalLength = 4 + NodeState::DataLength );
private:
Uint32 qmgrRef;
Uint32 version; // Version of NDB node
Uint32 apiHeartbeatFrequency;
NodeState nodeState;
+ Uint32 endian; // Endian of NDB node
};
#endif
--- 1.4/storage/ndb/include/kernel/signaldata/CmRegSignalData.hpp 2007-05-09 10:19:39 +08:00
+++ 1.5/storage/ndb/include/kernel/signaldata/CmRegSignalData.hpp 2007-05-09 10:19:39 +08:00
@@ -159,7 +159,7 @@ class CmNodeInfoReq {
friend class Qmgr;
public:
- STATIC_CONST( SignalLength = 3 );
+ STATIC_CONST( SignalLength = 4 );
private:
/**
@@ -168,6 +168,7 @@ private:
Uint32 nodeId;
Uint32 dynamicId;
Uint32 version;
+ Uint32 endian; //Endian of NDB node
};
class CmNodeInfoRef {
@@ -195,12 +196,13 @@ class CmNodeInfoConf {
friend class Qmgr;
public:
- STATIC_CONST( SignalLength = 3 );
+ STATIC_CONST( SignalLength = 4 );
private:
Uint32 nodeId;
Uint32 dynamicId;
Uint32 version;
+ Uint32 endian; //Endian of NDB node
};
#endif
--- 1.2/storage/ndb/include/kernel/signaldata/TupCommit.hpp 2007-05-09 10:19:39 +08:00
+++ 1.3/storage/ndb/include/kernel/signaldata/TupCommit.hpp 2007-05-09 10:19:39 +08:00
@@ -36,7 +36,7 @@ class TupCommitReq {
friend bool printTUPCOMMITREQ(FILE * output, const Uint32 * theData, Uint32 len, Uint16 receiverBlockNo);
public:
- STATIC_CONST( SignalLength = 3 );
+ STATIC_CONST( SignalLength = 4 );
private:
@@ -46,6 +46,7 @@ private:
Uint32 opPtr;
Uint32 gci;
Uint32 hashValue;
+ Uint32 applRef;
};
#endif
--- 1.5/storage/ndb/include/kernel/signaldata/TuxBound.hpp 2007-05-09 10:19:39 +08:00
+++ 1.6/storage/ndb/include/kernel/signaldata/TuxBound.hpp 2007-05-09 10:19:39 +08:00
@@ -38,7 +38,7 @@ public:
InvalidCharFormat = 744,
TooMuchAttrInfo = 823
};
- STATIC_CONST( SignalLength = 3 );
+ STATIC_CONST( SignalLength = 4 );
private:
/*
* Error code set by TUX. Zero means no error.
@@ -52,6 +52,10 @@ private:
* Number of words of bound info included after fixed signal data.
*/
Uint32 boundAiLength;
+ /*
+ * Send the scan API blockref to TUX, so that can handle endian for BOUND_INFO.
+ */
+ Uint32 scanApiBlockref;
Uint32 data[1];
};
--- 1.11/storage/ndb/include/util/SimpleProperties.hpp 2007-05-09 10:19:39 +08:00
+++ 1.12/storage/ndb/include/util/SimpleProperties.hpp 2007-05-09 10:19:39 +08:00
@@ -71,6 +71,15 @@ public:
OutOfMemory = 6 // Only used when packing
};
+ /**
+ * SwapStatus - The number of words have been swapped returned from getValue
+ */
+ enum SwapStatus {
+ SwappedZeroWord = 0, // didn't swap any word in getValue
+ SwappedOneWord = 1, // has swapped 1 word in getValue
+ SwappedTwoWords = 2 // has swapped 2 words in getValue
+ };
+
/**
* Unpack
*/
@@ -141,6 +150,20 @@ public:
*/
void printAll(NdbOut& ndbout);
+ /**
+ * Get the need convert endian flag.
+ */
+ virtual bool needConvertEndian() const { return false; };
+ /**
+ * Set the has converted endian flag.
+ */
+ virtual void hasConvertedEndian(bool has_converted_endian) {};
+
+ /**
+ * Get the swap status in getValue.
+ */
+ SwapStatus getSwapStatus() const;
+
private:
bool readValue();
@@ -151,6 +174,7 @@ public:
Uint32 m_strLen; // Including 0-byte in words
};
ValueType m_type;
+ SwapStatus m_swapStatus;
protected:
Reader();
virtual void reset() = 0;
@@ -172,6 +196,11 @@ public:
bool add(Uint16 key, Uint32 value);
bool add(Uint16 key, const char * value);
bool add(Uint16 key, const void* value, int len);
+ /**
+ * Get the need convert endian flag.
+ */
+ virtual bool needConvertEndian() const { return false; };
+
protected:
virtual ~Writer() {}
virtual bool reset() = 0;
@@ -179,6 +208,7 @@ public:
virtual bool putWords(const Uint32 * src, Uint32 len) = 0;
private:
bool add(const char* value, int len);
+ bool add16(const char* value, int len);
};
};
@@ -187,7 +217,7 @@ public:
*/
class SimplePropertiesLinearReader : public SimpleProperties::Reader {
public:
- SimplePropertiesLinearReader(const Uint32 * src, Uint32 len);
+ SimplePropertiesLinearReader(const Uint32 * src, Uint32 len, bool needConvertEndian = false);
virtual ~SimplePropertiesLinearReader() {}
virtual void reset();
@@ -195,10 +225,20 @@ public:
virtual bool getWord(Uint32 * dst);
virtual bool peekWord(Uint32 * dst) const ;
virtual bool peekWords(Uint32 * dst, Uint32 len) const;
+ /**
+ * Get the need convert endian flag.
+ */
+ virtual bool needConvertEndian() const;
+ /**
+ * Set the has converted endian flag.
+ */
+ virtual void hasConvertedEndian(bool has_converted_endian);
private:
Uint32 m_len;
Uint32 m_pos;
- const Uint32 * m_src;
+ Uint32 * m_src;
+ bool m_convertEndian;
+ bool m_hasConvertedEndian;
};
/**
@@ -206,17 +246,22 @@ private:
*/
class LinearWriter : public SimpleProperties::Writer {
public:
- LinearWriter(Uint32 * src, Uint32 len);
+ LinearWriter(Uint32 * src, Uint32 len, bool needConvertEndian = false);
virtual ~LinearWriter() {}
virtual bool reset();
virtual bool putWord(Uint32 val);
virtual bool putWords(const Uint32 * src, Uint32 len);
Uint32 getWordsUsed() const;
+ /**
+ * Get the need convert endian flag.
+ */
+ virtual bool needConvertEndian() const;
private:
Uint32 m_len;
Uint32 m_pos;
Uint32 * m_src;
+ bool m_convertEndian;
};
/**
@@ -224,15 +269,20 @@ private:
*/
class UtilBufferWriter : public SimpleProperties::Writer {
public:
- UtilBufferWriter(class UtilBuffer & buf);
+ UtilBufferWriter(class UtilBuffer & buf, bool needConvertEndian = false);
virtual ~UtilBufferWriter() {}
virtual bool reset();
virtual bool putWord(Uint32 val);
virtual bool putWords(const Uint32 * src, Uint32 len);
Uint32 getWordsUsed() const;
+ /**
+ * Get the need convert endian flag.
+ */
+ virtual bool needConvertEndian() const;
private:
class UtilBuffer & m_buf;
+ bool m_convertEndian;
};
/**
@@ -244,7 +294,8 @@ private:
class SimplePropertiesSectionReader : public SimpleProperties::Reader {
public:
SimplePropertiesSectionReader(struct SegmentedSectionPtr &,
- class SectionSegmentPool &);
+ class SectionSegmentPool &,
+ bool needConvertEndian = false);
virtual ~SimplePropertiesSectionReader() {}
virtual void reset();
@@ -255,12 +306,24 @@ public:
Uint32 getSize() const;
bool getWords(Uint32 * dst, Uint32 len);
+ /**
+ * Get the need convert endian flag.
+ */
+ virtual bool needConvertEndian() const;
+
+ /**
+ * Set the has converted endian flag.
+ */
+ virtual void hasConvertedEndian(bool has_converted_endian);
+
private:
Uint32 m_pos;
Uint32 m_len;
class SectionSegmentPool & m_pool;
struct SectionSegment * m_head;
struct SectionSegment * m_currentSegment;
+ bool m_convertEndian;
+ bool m_hasConvertedEndian;
};
inline
@@ -277,7 +340,7 @@ Uint32 SimplePropertiesSectionReader::ge
*/
class SimplePropertiesSectionWriter : public SimpleProperties::Writer {
public:
- SimplePropertiesSectionWriter(class SectionSegmentPool &);
+ SimplePropertiesSectionWriter(class SectionSegmentPool &, bool needConvertEndian = false);
virtual ~SimplePropertiesSectionWriter() {}
virtual bool reset();
@@ -288,6 +351,11 @@ public:
* This "unlinks" the writer from the memory
*/
void getPtr(struct SegmentedSectionPtr & dst);
+
+ /**
+ * Get the need convert endian flag.
+ */
+ virtual bool needConvertEndian() const;
private:
Int32 m_pos;
@@ -296,6 +364,7 @@ private:
struct SectionSegment * m_head;
Uint32 m_prevPtrI; // Prev to m_currentSegment
struct SectionSegment * m_currentSegment;
+ bool m_convertEndian;
};
#endif
--- 1.14/storage/ndb/src/common/debugger/signaldata/SignalNames.cpp 2007-05-09 10:19:39 +08:00
+++ 1.15/storage/ndb/src/common/debugger/signaldata/SignalNames.cpp 2007-05-09 10:19:39 +08:00
@@ -327,6 +327,7 @@ const GsnName SignalNames [] = {
,{ GSN_TUP_ADD_ATTRREF, "TUP_ADD_ATTRREF" }
,{ GSN_TUP_ADD_ATTRREQ, "TUP_ADD_ATTRREQ" }
,{ GSN_TUP_ATTRINFO, "TUP_ATTRINFO" }
+ ,{ GSN_TUP_ORIG_ATTRINFO, "TUP_ORIG_ATTRINFO" }
,{ GSN_TUP_COMMITREQ, "TUP_COMMITREQ" }
,{ GSN_TUPFRAGCONF, "TUPFRAGCONF" }
,{ GSN_TUPFRAGREF, "TUPFRAGREF" }
--- 1.8/storage/ndb/src/common/transporter/Packer.cpp 2007-05-09 10:19:39 +08:00
+++ 1.9/storage/ndb/src/common/transporter/Packer.cpp 2007-05-09 10:19:39 +08:00
@@ -15,6 +15,7 @@
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
#include <ndb_global.h>
+#include <ndb_endian.h>
#include "Packer.hpp"
#include <TransporterRegistry.hpp>
@@ -41,11 +42,13 @@ TransporterRegistry::unpack(Uint32 * rea
Uint32 word3 = readPtr[2];
loop_count++;
-#if 0
- if(Protocol6::getByteOrder(word1) != MY_OWN_BYTE_ORDER){
- //Do funky stuff
+ // Handle byte order of first 3 words
+ Uint32 myOwnByteOrder = ndbCheckEndian();
+ if (Protocol6::getByteOrder(word1) != myOwnByteOrder){
+ word1 = ndbSwapOneWord32(word1);
+ word2 = ndbSwapOneWord32(word2);
+ word3 = ndbSwapOneWord32(word3);
}
-#endif
const Uint16 messageLen32 = Protocol6::getMessageLength(word1);
const Uint32 messageLenBytes = ((Uint32)messageLen32) << 2;
@@ -60,6 +63,12 @@ TransporterRegistry::unpack(Uint32 * rea
break;
}//if
+ // Handle byte order of signal data
+ if (Protocol6::getByteOrder(word1) != myOwnByteOrder){
+ // swap the left data
+ ndbSwapManyWords32(&readPtr[3], messageLen32 - 3);
+ }
+
if(Protocol6::getCheckSumIncluded(word1)){
const Uint32 tmpLen = messageLen32 - 1;
const Uint32 checkSumSent = readPtr[tmpLen];
@@ -124,11 +133,13 @@ TransporterRegistry::unpack(Uint32 * rea
Uint32 word3 = readPtr[2];
loop_count++;
-#if 0
- if(Protocol6::getByteOrder(word1) != MY_OWN_BYTE_ORDER){
- //Do funky stuff
- }//if
-#endif
+ // Handle byte order of first 3 words
+ Uint32 myOwnByteOrder = ndbCheckEndian();
+ if (Protocol6::getByteOrder(word1) != myOwnByteOrder){
+ word1 = ndbSwapOneWord32(word1);
+ word2 = ndbSwapOneWord32(word2);
+ word3 = ndbSwapOneWord32(word3);
+ }
const Uint16 messageLen32 = Protocol6::getMessageLength(word1);
const Uint32 messageLenBytes = ((Uint32)messageLen32) << 2;
@@ -142,6 +153,12 @@ TransporterRegistry::unpack(Uint32 * rea
break;
}//if
+ // Handle byte order of signal data
+ if (Protocol6::getByteOrder(word1) != myOwnByteOrder){
+ // swap the left data
+ ndbSwapManyWords32(&readPtr[3], messageLen32 - 3);
+ }
+
if(Protocol6::getCheckSumIncluded(word1)){
const Uint32 tmpLen = messageLen32 - 1;
const Uint32 checkSumSent = readPtr[tmpLen];
@@ -222,11 +239,14 @@ TransporterRegistry::unpack(Uint32 * rea
Uint32 word2 = readPtr[1];
Uint32 word3 = readPtr[2];
loop_count++;
-#if 0
- if(Protocol6::getByteOrder(word1) != MY_OWN_BYTE_ORDER){
- //Do funky stuff
+
+ // Handle byte order of first 3 words
+ Uint32 myOwnByteOrder = ndbCheckEndian();
+ if (Protocol6::getByteOrder(word1) != myOwnByteOrder){
+ word1 = ndbSwapOneWord32(word1);
+ word2 = ndbSwapOneWord32(word2);
+ word3 = ndbSwapOneWord32(word3);
}
-#endif
const Uint16 messageLen32 = Protocol6::getMessageLength(word1);
@@ -236,6 +256,12 @@ TransporterRegistry::unpack(Uint32 * rea
return readPtr;
}//if
+ // Handle byte order of signal data
+ if (Protocol6::getByteOrder(word1) != myOwnByteOrder){
+ // swap the left data
+ ndbSwapManyWords32(&readPtr[3], messageLen32 - 3);
+ }
+
if(Protocol6::getCheckSumIncluded(word1)){
const Uint32 tmpLen = messageLen32 - 1;
const Uint32 checkSumSent = readPtr[tmpLen];
@@ -293,11 +319,14 @@ TransporterRegistry::unpack(Uint32 * rea
Uint32 word2 = readPtr[1];
Uint32 word3 = readPtr[2];
loop_count++;
-#if 0
- if(Protocol6::getByteOrder(word1) != MY_OWN_BYTE_ORDER){
- //Do funky stuff
- }//if
-#endif
+
+ // Handle byte order of first 3 words
+ Uint32 myOwnByteOrder = ndbCheckEndian();
+ if (Protocol6::getByteOrder(word1) != myOwnByteOrder){
+ word1 = ndbSwapOneWord32(word1);
+ word2 = ndbSwapOneWord32(word2);
+ word3 = ndbSwapOneWord32(word3);
+ }
const Uint16 messageLen32 = Protocol6::getMessageLength(word1);
if(messageLen32 == 0 || messageLen32 > MAX_MESSAGE_SIZE){
@@ -306,6 +335,12 @@ TransporterRegistry::unpack(Uint32 * rea
return readPtr;
}//if
+ // Handle byte order of signal data
+ if (Protocol6::getByteOrder(word1) != myOwnByteOrder){
+ // swap the left data
+ ndbSwapManyWords32(&readPtr[3], messageLen32 - 3);
+ }
+
if(Protocol6::getCheckSumIncluded(word1)){
const Uint32 tmpLen = messageLen32 - 1;
const Uint32 checkSumSent = readPtr[tmpLen];
@@ -420,6 +455,8 @@ Packer::pack(Uint32 * insertPtr,
Uint32 word2 = 0;
Uint32 word3 = 0;
+ Uint32 ownByteOrder = ndbCheckEndian();
+ Protocol6::setByteOrder(word1, ownByteOrder);
Protocol6::setPrio(word1, prio);
Protocol6::setMessageLength(word1, len32);
Protocol6::createProtocol6Header(word1, word2, word3, header);
@@ -479,6 +516,8 @@ Packer::pack(Uint32 * insertPtr,
Uint32 word2 = 0;
Uint32 word3 = 0;
+ Uint32 ownByteOrder = ndbCheckEndian();
+ Protocol6::setByteOrder(word1, ownByteOrder);
Protocol6::setPrio(word1, prio);
Protocol6::setMessageLength(word1, len32);
Protocol6::createProtocol6Header(word1, word2, word3, header);
--- 1.11/storage/ndb/src/common/util/SimpleProperties.cpp 2007-05-09 10:19:39 +08:00
+++ 1.12/storage/ndb/src/common/util/SimpleProperties.cpp 2007-05-09 10:19:39 +08:00
@@ -19,6 +19,8 @@
#include <NdbOut.hpp>
#include <NdbTCP.h>
#include <UtilBuffer.hpp>
+#include <signaldata/DictTabInfo.hpp>
+#include <ndb_endian.h>
bool
SimpleProperties::Writer::first(){
@@ -30,6 +32,16 @@ SimpleProperties::Writer::add(Uint16 key
Uint32 head = Uint32Value;
head <<= 16;
head += key;
+ bool need_convert_endian = needConvertEndian();
+ /**
+ * If the endian of the sender and receiver are different,
+ * the byte order of the data will be swapped at the receiver end,
+ * so swap the byte order beforehand.
+ */
+ if (need_convert_endian) {
+ head = ndbSwapOneWord32(head);
+ value = ndbSwapOneWord32(value);
+ }
if(!putWord(htonl(head)))
return false;
@@ -38,12 +50,22 @@ SimpleProperties::Writer::add(Uint16 key
bool
SimpleProperties::Writer::add(const char * value, int len){
+ bool need_convert_endian = needConvertEndian();
const Uint32 valLen = (len + 3) / 4;
- if ((len % 4) == 0)
+ if ((len % 4) == 0) {
+ if (need_convert_endian && valLen > 0) {
+ // swap byte order for character strings
+ ndbSwapManyWords32((Uint32*)value, valLen);
+ }
return putWords((Uint32*)value, valLen);
+ }
const Uint32 putLen= valLen - 1;
+ if (need_convert_endian && putLen > 0) {
+ // swap byte order for character strings
+ ndbSwapManyWords32((Uint32*)value, putLen);
+ }
if (!putWords((Uint32*)value, putLen))
return false;
@@ -56,6 +78,47 @@ SimpleProperties::Writer::add(const char
memcpy(tmp.lastBytes,
value + putLen*4,
len - putLen*4);
+ if (need_convert_endian && len > 0) {
+ // swap byte order for character strings
+ ndbSwapManyWords32(&(tmp.lastWord), 1);
+ }
+ return putWord(tmp.lastWord);
+}
+
+bool
+SimpleProperties::Writer::add16(const char * value, int len){
+ bool need_convert_endian = needConvertEndian();
+ const Uint32 valLen = (len + 3) / 4;
+
+ if ((len % 4) == 0) {
+ if (need_convert_endian && valLen > 0) {
+ // swap byte order for 16-bit words.
+ ndbSwapManyWords16((Uint32*)value, valLen);
+ }
+ return putWords((Uint32*)value, valLen);
+ }
+
+ const Uint32 putLen= valLen - 1;
+ if (need_convert_endian && putLen > 0) {
+ // swap byte order for 16-bit words.
+ ndbSwapManyWords16((Uint32*)value, putLen);
+ }
+ if (!putWords((Uint32*)value, putLen))
+ return false;
+
+ // Special handling of last bytes
+ union {
+ Uint32 lastWord;
+ char lastBytes[4];
+ } tmp;
+ tmp.lastWord =0 ;
+ memcpy(tmp.lastBytes,
+ value + putLen*4,
+ len - putLen*4);
+ if (need_convert_endian && len > 0) {
+ // swap byte order for 16-bit word.
+ ndbSwapManyWords16(&(tmp.lastWord), 1);
+ }
return putWord(tmp.lastWord);
}
@@ -64,12 +127,31 @@ SimpleProperties::Writer::add(Uint16 key
Uint32 head = StringValue;
head <<= 16;
head += key;
+
+ bool need_convert_endian = needConvertEndian();
+ Uint32 strLen = strlen(value) + 1; // Including NULL-byte
+ /**
+ * If the endian of the sender and receiver are different,
+ * the byte order of the data will be swapped at the receiver end,
+ * so swap the byte order beforehand.
+ */
+ if (need_convert_endian) {
+ head = ndbSwapOneWord32(head);
+ strLen = ndbSwapOneWord32(strLen);
+ }
if(!putWord(htonl(head)))
return false;
- Uint32 strLen = strlen(value) + 1; // Including NULL-byte
if(!putWord(htonl(strLen)))
return false;
+ /**
+ * Because strLen will be used later, should swap its byte order
+ * back again.
+ */
+ if (need_convert_endian) {
+ strLen = ndbSwapOneWord32(strLen);
+ }
+
return add(value, (int)strLen);
}
@@ -79,12 +161,38 @@ SimpleProperties::Writer::add(Uint16 key
Uint32 head = BinaryValue;
head <<= 16;
head += key;
+ bool need_convert_endian = needConvertEndian();
+ /**
+ * If the endian of the sender and receiver are different,
+ * the byte order of the data will be swapped at the receiver end,
+ * so swap the byte order beforehand.
+ */
+ if (need_convert_endian) {
+ head = ndbSwapOneWord32(head);
+ len = ndbSwapOneWord32((Uint32)len);
+ }
+
if(!putWord(htonl(head)))
return false;
if(!putWord(htonl(len)))
return false;
- return add((const char*)value, len);
+ /**
+ * Because len will be used later, should swap its byte order
+ * back again.
+ */
+ if (need_convert_endian) {
+ len = ndbSwapOneWord32((Uint32)len);
+ }
+
+ switch (key) {
+ case DictTabInfo::ReplicaData:
+ case DictTabInfo::FragmentData:
+ return add16((const char*)value, len);
+ default:
+ // Treat all the other Binary attributes as char string.
+ return add((const char*)value, len);
+ }
}
SimpleProperties::Reader::Reader(){
@@ -113,6 +221,11 @@ SimpleProperties::Reader::getKey() const
return m_key;
}
+SimpleProperties::SwapStatus
+SimpleProperties::Reader::getSwapStatus() const{
+ return m_swapStatus;
+}
+
Uint16
SimpleProperties::Reader::getValueLen() const {
switch(m_type){
@@ -137,7 +250,7 @@ SimpleProperties::Reader::getUint32() co
return m_ui32_value;
}
-char *
+char *
SimpleProperties::Reader::getString(char * dst) const {
if(peekWords((Uint32*)dst, m_itemLen))
return dst;
@@ -148,35 +261,45 @@ bool
SimpleProperties::Reader::readValue(){
if(!step(m_itemLen)){
m_type = InvalidValue;
+ m_swapStatus = SwappedZeroWord;
return false;
}
Uint32 tmp;
if(!getWord(&tmp)){
m_type = InvalidValue;
+ m_swapStatus = SwappedZeroWord;
return false;
}
tmp = ntohl(tmp);
+
m_key = tmp & 0xFFFF;
m_type = (SimpleProperties::ValueType)(tmp >> 16);
switch(m_type){
case Uint32Value:
m_itemLen = 1;
- if(!peekWord(&m_ui32_value))
+ if(!peekWord(&m_ui32_value)) {
+ m_swapStatus = SwappedOneWord;
return false;
+ }
m_ui32_value = ntohl(m_ui32_value);
+ m_swapStatus = SwappedTwoWords;
return true;
case StringValue:
case BinaryValue:
- if(!getWord(&tmp))
+ if(!getWord(&tmp)) {
+ m_swapStatus = SwappedOneWord;
return false;
+ }
m_strLen = ntohl(tmp);
m_itemLen = (m_strLen + 3)/4;
+ m_swapStatus = SwappedTwoWords;
return true;
default:
m_itemLen = 0;
m_type = InvalidValue;
+ m_swapStatus = SwappedOneWord;
return false;
}
}
@@ -291,6 +414,11 @@ SimpleProperties::pack(Writer & it, cons
void
SimpleProperties::Reader::printAll(NdbOut& ndbout){
+ /**
+ * Should not handle endian here.
+ * It should has been handled before this function.
+ */
+ hasConvertedEndian(true);
char tmp[1024];
for(first(); valid(); next()){
switch(getValueType()){
@@ -318,13 +446,18 @@ SimpleProperties::Reader::printAll(NdbOu
<< " type: " << (Uint32)getValueType() << endl;
}
}
+ // reset flag
+ hasConvertedEndian(false);
}
SimplePropertiesLinearReader::SimplePropertiesLinearReader
-(const Uint32 * src, Uint32 len){
- m_src = src;
+(const Uint32 * src, Uint32 len, bool needConvertEndian)
+{
+ m_src = const_cast<Uint32 *>(src);
m_len = len;
m_pos = 0;
+ m_convertEndian = needConvertEndian;
+ m_hasConvertedEndian = false;
first();
}
@@ -342,6 +475,22 @@ SimplePropertiesLinearReader::step(Uint3
bool
SimplePropertiesLinearReader::getWord(Uint32 * dst) {
if(m_pos<m_len){
+ /**
+ * If the endian of the sender and receiver are different,
+ * the byte order of the data will be swapped at the receiver end,
+ * so swap the byte order beforehand.
+ */
+ if (m_convertEndian && !m_hasConvertedEndian) {
+ ndbSwapManyWords32(&m_src[m_pos], 1);
+ }
+
+#if 0
+ // For test
+ for (Uint32 i = 0; i < 4; i++) {
+ ndbout_c("test: dst[%u]: '%x'", i, ((unsigned char*)&m_src[m_pos])[i]);
+ }
+#endif
+
* dst = m_src[m_pos++];
return true;
}
@@ -351,6 +500,22 @@ SimplePropertiesLinearReader::getWord(Ui
bool
SimplePropertiesLinearReader::peekWord(Uint32 * dst) const {
if(m_pos<m_len){
+ /**
+ * If the endian of the sender and receiver are different,
+ * the byte order of the data will be swapped at the receiver end,
+ * so swap the byte order beforehand.
+ */
+ if (m_convertEndian && !m_hasConvertedEndian) {
+ ndbSwapManyWords32(&m_src[m_pos], 1);
+ }
+
+#if 0
+ // For test
+ for (Uint32 i = 0; i < 4; i++) {
+ ndbout_c("test: dst[%u]: '%x'", i, ((unsigned char*)&m_src[m_pos])[i]);
+ }
+#endif
+
* dst = m_src[m_pos];
return true;
}
@@ -360,15 +525,76 @@ SimplePropertiesLinearReader::peekWord(U
bool
SimplePropertiesLinearReader::peekWords(Uint32 * dst, Uint32 len) const {
if(m_pos + len <= m_len){
+ if (m_convertEndian && !m_hasConvertedEndian) {
+ /**
+ * It will call getValue() in the Constructor, and getValue() will
+ * handle endian conversion, and it maybe will call reset() then
+ * getWords() later, thus must consider it here, otherwise the first
+ * several words may be swapped 2 times.
+ */
+ if (m_pos == 0) {
+ SimpleProperties::SwapStatus swapStatus = getSwapStatus();
+ switch(swapStatus) {
+ case SimpleProperties::SwappedZeroWord:
+ // no need action
+ break;
+ case SimpleProperties::SwappedOneWord:
+ // turn it back
+ ndbSwapManyWords32(&m_src[m_pos], 1);
+ break;
+ case SimpleProperties::SwappedTwoWords:
+ // turn it back
+ ndbSwapManyWords32(&m_src[m_pos], 2);
+ break;
+ default:
+ break;
+ }//switch
+ }//if
+
+ Uint16 key = getKey();
+ switch (key) {
+ case DictTabInfo::ReplicaData:
+ case DictTabInfo::FragmentData:
+ // swap byte order for 16-bit words.
+ ndbSwapManyWords16(&m_src[m_pos], len);
+ break;
+ default:
+ /**
+ * swap byte order for 32-bit words.
+ * Treat all the other Binary attributes as char string.
+ */
+ ndbSwapManyWords32(&m_src[m_pos], len);
+ break;
+ }
+ }
+
+#if 0
+ // For test
+ for (Uint32 i = 0; i < len<<2; i++) {
+ ndbout_c("test: dst[%u]: '%x'", i, ((unsigned char *)&m_src[m_pos])[i]);
+ }
+#endif
+
memcpy(dst, &m_src[m_pos], 4 * len);
return true;
}
return false;
}
-LinearWriter::LinearWriter(Uint32 * src, Uint32 len){
+bool
+SimplePropertiesLinearReader::needConvertEndian() const {
+ return m_convertEndian;
+}
+
+void
+SimplePropertiesLinearReader::hasConvertedEndian(bool has_converted_endian) {
+ m_hasConvertedEndian = has_converted_endian;
+}
+
+LinearWriter::LinearWriter(Uint32 * src, Uint32 len, bool needConvertEndian){
m_src = src;
m_len = len;
+ m_convertEndian = needConvertEndian;
reset();
}
@@ -396,9 +622,13 @@ LinearWriter::putWords(const Uint32 * sr
Uint32
LinearWriter::getWordsUsed() const { return m_pos;}
-UtilBufferWriter::UtilBufferWriter(UtilBuffer & b)
+bool
+LinearWriter::needConvertEndian() const { return m_convertEndian; }
+
+UtilBufferWriter::UtilBufferWriter(UtilBuffer & b, bool needConvertEndian)
: m_buf(b)
{
+ m_convertEndian = needConvertEndian;
reset();
}
@@ -417,6 +647,9 @@ UtilBufferWriter::putWords(const Uint32
Uint32
UtilBufferWriter::getWordsUsed() const { return m_buf.length() / 4;}
+
+bool
+UtilBufferWriter::needConvertEndian() const { return m_convertEndian;}
#if 0
LinearPagesReader::LinearPagesReader(const Uint32 * base,
--- 1.34/storage/ndb/src/kernel/blocks/cmvmi/Cmvmi.cpp 2007-05-09 10:19:39 +08:00
+++ 1.35/storage/ndb/src/kernel/blocks/cmvmi/Cmvmi.cpp 2007-05-09 10:19:39 +08:00
@@ -218,8 +218,46 @@ void Cmvmi::execEVENT_REP(Signal* signal
if(ptr.p->logLevel.getLogLevel(eventCategory) < threshold){
continue;
}
+ /**
+ * If the event type is InfoEvent or WarningEvent, it will send the char
+ * string event info to the MGM node.
+ * So if the endianness of MGM node and own node are different, should
+ * swap the char string event info here, so that no need to swap it on
+ * the MGM node.
+ * We should compare the endian of the sender node and own node here.
+ */
+ const Uint32 senderRef = ptr.p->blockRef;
+ bool needConvertEndian = compareEndianWithOwn(senderRef);
+ Uint32 noOfWords;
+
+ if (needConvertEndian) {
+ switch(eventType) {
+ case NDB_LE_InfoEvent:
+ case NDB_LE_WarningEvent:
+ noOfWords = signal->header.theLength - 1; //subtract theData[0]
+ ndbSwapManyWords32(&(signal->theData[1]), noOfWords);
+ break;
+ default:
+ break;
+ }
+ }
sendSignal(ptr.p->blockRef, GSN_EVENT_REP, signal, signal->length(), JBB);
+
+ /**
+ * Turn it back again, so that it can be reused.
+ */
+ if (needConvertEndian) {
+ switch(eventType) {
+ case NDB_LE_InfoEvent:
+ case NDB_LE_WarningEvent:
+ noOfWords = signal->header.theLength - 1; //subtract theData[0]
+ ndbSwapManyWords32(&(signal->theData[1]), noOfWords);
+ break;
+ default:
+ break;
+ }
+ }
}
if(clogLevel.getLogLevel(eventCategory) < threshold){
--- 1.78/storage/ndb/src/kernel/blocks/dbacc/DbaccMain.cpp 2007-05-09 10:19:39 +08:00
+++ 1.79/storage/ndb/src/kernel/blocks/dbacc/DbaccMain.cpp 2007-05-09 10:19:39 +08:00
@@ -3186,6 +3186,11 @@ Dbacc::readTablePk(Uint32 localkey1, Uin
{
Uint32 fragPageId = localkey1 >> MAX_TUPLES_BITS;
Uint32 pageIndex = localkey1 & ((1 << MAX_TUPLES_BITS ) - 1);
+ /**
+ * Because the keyinfo in DBACC has been handled endian, set c_tup->capiBlockref
+ * to 0, let it no need to handle endian while reading key attributes from DBTUP.
+ */
+ c_tup->capiBlockref = 0;
ret = c_tup->accReadPk(tableId, fragId, fragPageId, pageIndex,
ckeys, true);
}
--- 1.107/storage/ndb/src/kernel/blocks/dbdict/Dbdict.cpp 2007-05-09 10:19:39 +08:00
+++ 1.108/storage/ndb/src/kernel/blocks/dbdict/Dbdict.cpp 2007-05-09 10:19:39 +08:00
@@ -346,12 +346,20 @@ void Dbdict::packTableIntoPages(Signal*
const Uint32 type= signal->theData[2];
const Uint32 pageId= signal->theData[3];
+ /**
+ * Compare the endian of the sender node and own node here
+ * to judge whether need convert endian.
+ */
+ const Uint32 senderRef = c_retrieveRecord.blockRef;
+ bool needConvertEndian = compareEndianWithOwn(senderRef);
+
PageRecordPtr pagePtr;
c_pageRecordArray.getPtr(pagePtr, pageId);
memset(&pagePtr.p->word[0], 0, 4 * ZPAGE_HEADER_SIZE);
LinearWriter w(&pagePtr.p->word[ZPAGE_HEADER_SIZE],
- ZMAX_PAGES_OF_TABLE_DEFINITION * ZSIZE_OF_PAGES_IN_WORDS);
+ ZMAX_PAGES_OF_TABLE_DEFINITION * ZSIZE_OF_PAGES_IN_WORDS,
+ needConvertEndian);
w.first();
switch((DictTabInfo::TableType)type) {
case DictTabInfo::SystemTable:
@@ -481,8 +489,17 @@ Dbdict::packTableIntoPages(SimplePropert
Uint16 *data = (Uint16*)&signal->theData[25];
Uint32 count = 2 + data[0] * data[1];
w.add(DictTabInfo::ReplicaDataLen, 2*count);
- for (Uint32 i = 0; i < count; i++)
+ for (Uint32 i = 0; i < count; i++) {
+ /**
+ * If the endian of the sender and receiver are different,
+ * the byte order of the data will be swapped at the receiver end,
+ * so swap the byte order beforehand.
+ */
+ if (w.needConvertEndian()) {
+ data[i] = ndbSwapOneWord16(data[i]);
+ }
data[i] = htons(data[i]);
+ }
w.add(DictTabInfo::ReplicaData, data, 2*count);
}
else
@@ -3073,10 +3090,13 @@ Dbdict::restartCreateTab_readTableConf(S
ParseDictTabInfoRecord parseRecord;
parseRecord.requestType = DictTabInfo::GetTabInfoConf;
parseRecord.errorCode = 0;
-
+
+ const Uint32 senderRef = signal->senderBlockRef();
+ bool needConvertEndian = compareEndianWithOwn(senderRef);
+
Uint32 sz = c_readTableRecord.no_of_words;
- SimplePropertiesLinearReader r(pageRecPtr.p->word+ZPAGE_HEADER_SIZE, sz);
- handleTabInfoInit(r, &parseRecord);
+ SimplePropertiesLinearReader r(pageRecPtr.p->word+ZPAGE_HEADER_SIZE, sz, needConvertEndian);
+ handleTabInfoInit(r, &parseRecord, true);
if (parseRecord.errorCode != 0)
{
char buf[255];
@@ -3198,8 +3218,12 @@ Dbdict::execGET_TABINFO_CONF(Signal* sig
parseRecord.requestType = DictTabInfo::GetTabInfoConf;
parseRecord.errorCode = 0;
+ /**
+ * Because we convert endian in the reply of GET_TABINFOREQ,
+ * no need to convert endian here.
+ */
SimplePropertiesSectionReader r(tabInfoPtr, getSectionSegmentPool());
- handleTabInfoInit(r, &parseRecord);
+ handleTabInfoInit(r, &parseRecord, true);
ndbrequire(parseRecord.errorCode == 0);
// save to disk
@@ -3735,6 +3759,12 @@ Dbdict::execCREATE_TABLE_REQ(Signal* sig
CreateTableReq* const req = (CreateTableReq*)signal->getDataPtr();
const Uint32 senderRef = req->senderRef;
const Uint32 senderData = req->senderData;
+
+ /**
+ * Compare the endian of the sender node and own node here
+ * to judge whether need convert endian.
+ */
+ bool needConvertEndian = compareEndianWithOwn(senderRef);
ParseDictTabInfoRecord parseRecord;
do {
@@ -3770,9 +3800,9 @@ Dbdict::execCREATE_TABLE_REQ(Signal* sig
SegmentedSectionPtr ptr;
signal->getSection(ptr, CreateTableReq::DICT_TAB_INFO);
- SimplePropertiesSectionReader r(ptr, getSectionSegmentPool());
+ SimplePropertiesSectionReader r(ptr, getSectionSegmentPool(), needConvertEndian);
- handleTabInfoInit(r, &parseRecord);
+ handleTabInfoInit(r, &parseRecord, true);
releaseSections(signal);
if(parseRecord.errorCode != 0){
@@ -3913,6 +3943,12 @@ Dbdict::execALTER_TABLE_REQ(Signal* sign
const Uint32 tableId = req->tableId;
const Uint32 tableVersion = req->tableVersion;
ParseDictTabInfoRecord* aParseRecord;
+
+ /**
+ * Compare the endian of the sender node and own node here
+ * to judge whether need convert endian.
+ */
+ bool needConvertEndian = compareEndianWithOwn(senderRef);
// Get table definition
TableRecordPtr tablePtr;
@@ -3998,7 +4034,7 @@ Dbdict::execALTER_TABLE_REQ(Signal* sign
SegmentedSectionPtr ptr;
signal->getSection(ptr, AlterTableReq::DICT_TAB_INFO);
- SimplePropertiesSectionReader r(ptr, getSectionSegmentPool());
+ SimplePropertiesSectionReader r(ptr, getSectionSegmentPool(), needConvertEndian);
handleTabInfoInit(r, &parseRecord, false); // Will not save info
@@ -4025,6 +4061,10 @@ Dbdict::execALTER_TABLE_REQ(Signal* sign
alterTabPtr.p->m_dihAddFragPtr = RNIL;
alterTabPtr.p->m_alterTableId = tablePtr.p->tableId;
+ /**
+ * No need handle endian problem here, it will be handled in
+ * execALTER_TAB_REQ().
+ */
// Send prepare request to all alive nodes
SimplePropertiesSectionWriter w(getSectionSegmentPool());
packTableIntoPages(w, parseRecord.tablePtr);
@@ -4152,6 +4192,12 @@ Dbdict::execALTER_TAB_REQ(Signal * signa
AlterTabReq::RequestType requestType =
(AlterTabReq::RequestType) req->requestType;
+ /**
+ * Compare the endian of the sender node and own node here
+ * to judge whether need convert endian.
+ */
+ bool needConvertEndian = compareEndianWithOwn(senderRef);
+
SegmentedSectionPtr tabInfoPtr;
signal->getSection(tabInfoPtr, AlterTabReq::DICT_TAB_INFO);
@@ -4242,7 +4288,7 @@ Dbdict::execALTER_TAB_REQ(Signal * signa
parseRecord.requestType = DictTabInfo::AlterTableFromAPI;
parseRecord.errorCode = 0;
- SimplePropertiesSectionReader r(tabInfoPtr, getSectionSegmentPool());
+ SimplePropertiesSectionReader r(tabInfoPtr, getSectionSegmentPool(), needConvertEndian);
handleTabInfoInit(r, &parseRecord, false); // Will not save info
@@ -4404,6 +4450,10 @@ void Dbdict::execALTER_TAB_REF(Signal *
Uint32 tableId = tablePtr.p->tableId;
Uint32 tableVersion = tablePtr.p->tableVersion;
Uint32 gci = tablePtr.p->gciTableCreated;
+ /**
+ * No need handle endian problem here, it will be handled in
+ * execALTER_TAB_REQ().
+ */
SimplePropertiesSectionWriter w(getSectionSegmentPool());
packTableIntoPages(w, tablePtr);
SegmentedSectionPtr spDataPtr;
@@ -4540,6 +4590,10 @@ Dbdict::execALTER_TAB_CONF(Signal * sign
Uint32 tableId = tablePtr.p->tableId;
Uint32 tableVersion = tablePtr.p->tableVersion;
Uint32 gci = tablePtr.p->gciTableCreated;
+ /**
+ * No need to handle endian problem here, it will be handled in
+ * execALTER_TAB_REQ().
+ */
SimplePropertiesSectionWriter w(getSectionSegmentPool());
packTableIntoPages(w, tablePtr);
SegmentedSectionPtr spDataPtr;
@@ -4569,6 +4623,10 @@ Dbdict::execALTER_TAB_CONF(Signal * sign
// Send commit request to all alive nodes
TableRecordPtr tablePtr;
c_tableRecordPool.getPtr(tablePtr, tableId);
+ /**
+ * No need to handle endian problem here, it will be handled in
+ * execALTER_TAB_REQ().
+ */
SimplePropertiesSectionWriter w(getSectionSegmentPool());
packTableIntoPages(w, tablePtr);
SegmentedSectionPtr spDataPtr;
@@ -4931,6 +4989,10 @@ Dbdict::execCREATE_FRAGMENTATION_CONF(Si
create_obj_inc_schema_version(tabEntry->m_tableVersion);
/**
+ * No need to handle endian problem here, it will be handled in
+ * execCREATE_TAB_REQ().
+ */
+ /**
* Pack
*/
SimplePropertiesSectionWriter w(getSectionSegmentPool());
@@ -5175,6 +5237,12 @@ Dbdict::createTab_prepare(Signal* signal
const Uint32 gci = req->gci;
const Uint32 tableId = req->tableId;
const Uint32 tableVersion = req->tableVersion;
+ /**
+ * Compare the endian of the sender node and own node here
+ * to judge whether need convert endian.
+ */
+ const Uint32 senderRef = req->senderRef;
+ bool needConvertEndian = compareEndianWithOwn(senderRef);
SegmentedSectionPtr tabInfoPtr;
signal->getSection(tabInfoPtr, CreateTabReq::DICT_TAB_INFO);
@@ -5205,9 +5273,9 @@ Dbdict::createTab_prepare(Signal* signal
parseRecord.requestType = DictTabInfo::AddTableFromDict;
parseRecord.errorCode = 0;
- SimplePropertiesSectionReader r(tabInfoPtr, getSectionSegmentPool());
+ SimplePropertiesSectionReader r(tabInfoPtr, getSectionSegmentPool(), needConvertEndian);
- handleTabInfoInit(r, &parseRecord);
+ handleTabInfoInit(r, &parseRecord, true);
ndbrequire(parseRecord.errorCode == 0);
}
@@ -5971,7 +6039,14 @@ void Dbdict::handleTabInfoInit(SimplePro
// correct name, a new name or an already existing table.
/* ---------------------------------------------------------------- */
+ /**
+ * Should not handle endian here.
+ * It has been handled in the constructor while calling first().
+ */
+ it.hasConvertedEndian(true);
it.first();
+ // reset it
+ it.hasConvertedEndian(false);
SimpleProperties::UnpackStatus status;
c_tableDesc.init();
@@ -7323,6 +7398,12 @@ void Dbdict::execGET_TABINFOREQ(Signal*
}
GetTabInfoReq * const req = (GetTabInfoReq *)&signal->theData[0];
+ /**
+ * Compare the endian of the sender node and own node here
+ * to judge whether need convert endian.
+ */
+ const Uint32 senderRef = req->senderRef;
+ bool needConvertEndian = compareEndianWithOwn(senderRef);
/**
* If I get a GET_TABINFO_REQ from myself
@@ -7379,7 +7460,7 @@ void Dbdict::execGET_TABINFOREQ(Signal*
char tableName[MAX_TAB_NAME_SIZE];
SegmentedSectionPtr ssPtr;
signal->getSection(ssPtr,GetTabInfoReq::TABLE_NAME);
- SimplePropertiesSectionReader r0(ssPtr, getSectionSegmentPool());
+ SimplePropertiesSectionReader r0(ssPtr, getSectionSegmentPool(), needConvertEndian);
r0.reset(); // undo implicit first()
if(!r0.getWords((Uint32*)tableName, (len+3)/4)){
jam();
@@ -7554,6 +7635,11 @@ Dbdict::execLIST_TABLES_REQ(Signal* sign
conf->senderData = senderData;
conf->counter = 0;
Uint32 pos = 0;
+ /**
+ * Compare the endian of the sender node and own node here
+ * to judge whether need convert endian.
+ */
+ bool needConvertEndian = compareEndianWithOwn(senderRef);
DLHashTable<DictObject>::Iterator iter;
bool ok = c_obj_hash.first(iter);
@@ -7700,6 +7786,13 @@ Dbdict::execLIST_TABLES_REQ(Signal* sign
else
*p++ = 0;
}
+ // handle endian conversion for table name.
+ Uint32* tmpData = &conf->tableData[pos];
+ if (needConvertEndian) {
+ jam();
+ // need swap byte order for each 4-byte word of table name
+ ndbSwapManyWords32(tmpData, 1);
+ }
pos++;
if (pos >= ListTablesConf::DataLength) {
sendSignal(senderRef, GSN_LIST_TABLES_CONF, signal,
@@ -7799,6 +7892,7 @@ Dbdict::execCREATE_INDX_REQ(Signal* sign
// save attribute list
SegmentedSectionPtr ssPtr;
signal->getSection(ssPtr, CreateIndxReq::ATTRIBUTE_LIST_SECTION);
+ // Because type is Uint32, no need handle byte order here.
SimplePropertiesSectionReader r0(ssPtr, getSectionSegmentPool());
r0.reset(); // undo implicit first()
if (! r0.getWord(&opPtr.p->m_attrList.sz) ||
@@ -7810,9 +7904,16 @@ Dbdict::execCREATE_INDX_REQ(Signal* sign
createIndex_sendReply(signal, opPtr, opPtr.p->m_isMaster);
return;
}
+ /**
+ * Compare the endian of the client node and own node here
+ * to judge whether need convert endian.
+ */
+ const Uint32 clientRef = req->getUserRef();
+ bool needConvertEndian = compareEndianWithOwn(clientRef);
+
// save name and index table properties
signal->getSection(ssPtr, CreateIndxReq::INDEX_NAME_SECTION);
- SimplePropertiesSectionReader r1(ssPtr, getSectionSegmentPool());
+ SimplePropertiesSectionReader r1(ssPtr, getSectionSegmentPool(), needConvertEndian);
c_tableDesc.init();
SimpleProperties::UnpackStatus status = SimpleProperties::unpack(
r1, &c_tableDesc,
@@ -7954,6 +8055,9 @@ Dbdict::createIndex_slavePrepare(Signal*
void
Dbdict::createIndex_toCreateTable(Signal* signal, OpCreateIndexPtr opPtr)
{
+ /**
+ * Send CREATE_TABLE_REQ to own node, no need to handle byte order here.
+ */
union {
char tableName[MAX_TAB_NAME_SIZE];
char attributeName[MAX_ATTR_NAME_SIZE];
@@ -8913,6 +9017,9 @@ Dbdict::prepareUtilTransaction(Callback
Uint32 attrIds[],
const char *attrNames[])
{
+ /**
+ * Send to own node, no need consider endian problem
+ */
jam();
EVENT_TRACE;
@@ -9164,17 +9271,30 @@ Dbdict::createEvent_RT_USER_CREATE(Signa
ndbout_c("mask = %s", buf);
#endif
+ /**
+ * Compare the endian of the client node and own node here
+ * to judge whether need convert endian.
+ */
+ const Uint32 clientRef = evntRecPtr.p->m_request.getUserRef();
+ bool needConvertEndian = compareEndianWithOwn(clientRef);
+
// Interpret the long signal
SegmentedSectionPtr ssPtr;
// save name and event properties
signal->getSection(ssPtr, CreateEvntReq::EVENT_NAME_SECTION);
- SimplePropertiesSectionReader r0(ssPtr, getSectionSegmentPool());
+ SimplePropertiesSectionReader r0(ssPtr, getSectionSegmentPool(), needConvertEndian);
#ifdef EVENT_DEBUG
- r0.printAll(ndbout);
+ if (!needConvertEndian)
+ r0.printAll(ndbout);
#endif
// event name
+ /**
+ * Should not handle endian here.
+ * It has been handled in the constructor while calling first().
+ */
+ r0.hasConvertedEndian(true);
if ((!r0.first()) ||
(r0.getValueType() != SimpleProperties::StringValue) ||
(r0.getValueLen() <= 0)) {
@@ -9188,6 +9308,8 @@ Dbdict::createEvent_RT_USER_CREATE(Signa
createEvent_sendReply(signal, evntRecPtr);
DBUG_VOID_RETURN;
}
+ // reset it
+ r0.hasConvertedEndian(false);
r0.getString(evntRecPtr.p->m_eventRec.NAME);
{
int len = strlen(evntRecPtr.p->m_eventRec.NAME);
@@ -9690,14 +9812,27 @@ Dbdict::createEvent_RT_USER_GET(Signal*
ndbout_c("DBDICT(Coordinator) got GSN_CREATE_EVNT_REQ::RT_USER_GET evntRecPtr.i = (%d), ref = %u", evntRecPtr.i, evntRecPtr.p->m_request.getUserRef());
#endif
+ /**
+ * Compare the endian of the client node and own node here
+ * to judge whether need convert endian.
+ */
+ const Uint32 clientRef = evntRecPtr.p->m_request.getUserRef();
+ bool needConvertEndian = compareEndianWithOwn(clientRef);
+
SegmentedSectionPtr ssPtr;
signal->getSection(ssPtr, 0);
- SimplePropertiesSectionReader r0(ssPtr, getSectionSegmentPool());
+ SimplePropertiesSectionReader r0(ssPtr, getSectionSegmentPool(), needConvertEndian);
#ifdef EVENT_DEBUG
- r0.printAll(ndbout);
+ if (!needConvertEndian)
+ r0.printAll(ndbout);
#endif
+ /**
+ * Should not handle endian here.
+ * It has been handled in the constructor while calling first().
+ */
+ r0.hasConvertedEndian(true);
if ((!r0.first()) ||
(r0.getValueType() != SimpleProperties::StringValue) ||
(r0.getValueLen() <= 0)) {
@@ -9711,6 +9846,8 @@ Dbdict::createEvent_RT_USER_GET(Signal*
createEvent_sendReply(signal, evntRecPtr);
return;
}
+ // reset it
+ r0.hasConvertedEndian(false);
r0.getString(evntRecPtr.p->m_eventRec.NAME);
int len = strlen(evntRecPtr.p->m_eventRec.NAME);
@@ -9818,7 +9955,12 @@ void Dbdict::execCREATE_EVNT_CONF(Signal
ptr[0].p = (Uint32 *)evntRecPtr.p->m_eventRec.TABLE_NAME;
ptr[0].sz =
(strlen(evntRecPtr.p->m_eventRec.TABLE_NAME)+4)/4; // to make sure we have a null
-
+ /**
+ * If the user node and own node have different endian,
+ * should swap the byte order of table name.
+ * But because this method will be call many times, will
+ * swap in createEvent_sendReply() instead of this method.
+ */
createEvent_sendReply(signal, evntRecPtr, ptr, 1);
return;
@@ -10005,6 +10147,22 @@ void Dbdict::createEvent_sendReply(Signa
if (ptr) {
jam();
+
+ /**
+ * Compare the endian of the sender node and own node here
+ * to judge whether need convert endian.
+ */
+ bool needConvertEndian = compareEndianWithOwn(senderRef);
+
+ if (needConvertEndian) {
+ /**
+ * If the user node and own node have different endian,
+ * should swap the byte order of table name here, so that
+ * no need to handle it on user node.
+ */
+ ndbSwapManyWords32(ptr[0].p, ptr[0].sz);
+ }
+
sendSignal(senderRef, gsn, signal, signalLength, JBB, ptr, noLSP);
} else {
jam();
@@ -10516,15 +10674,28 @@ Dbdict::execDROP_EVNT_REQ(Signal* signal
OpDropEvent* evntRec = evntRecPtr.p;
evntRec->init(req);
+ /**
+ * Compare the endian of the client node and own node here
+ * to judge whether need convert endian.
+ */
+ const Uint32 clientRef = evntRecPtr.p->m_request.getUserRef();
+ bool needConvertEndian = compareEndianWithOwn(clientRef);
+
SegmentedSectionPtr ssPtr;
signal->getSection(ssPtr, 0);
- SimplePropertiesSectionReader r0(ssPtr, getSectionSegmentPool());
+ SimplePropertiesSectionReader r0(ssPtr, getSectionSegmentPool(), needConvertEndian);
#ifdef EVENT_DEBUG
- r0.printAll(ndbout);
+ if (!needConvertEndian)
+ r0.printAll(ndbout);
#endif
// event name
+ /**
+ * Should not handle endian here.
+ * It has been handled in the constructor while calling first().
+ */
+ r0.hasConvertedEndian(true);
if ((!r0.first()) ||
(r0.getValueType() != SimpleProperties::StringValue) ||
(r0.getValueLen() <= 0)) {
@@ -10538,6 +10709,8 @@ Dbdict::execDROP_EVNT_REQ(Signal* signal
dropEvent_sendReply(signal, evntRecPtr);
DBUG_VOID_RETURN;
}
+ // reset it
+ r0.hasConvertedEndian(false);
r0.getString(evntRecPtr.p->m_eventRec.NAME);
{
int len = strlen(evntRecPtr.p->m_eventRec.NAME);
@@ -12178,6 +12351,13 @@ Dbdict::execCREATE_TRIG_REQ(Signal* sign
signal, CreateTrigReq::SignalLength + 1, JBB);
return;
}
+ /**
+ * Compare the endian of the client node and own node here
+ * to judge whether need convert endian.
+ */
+ const Uint32 clientRef = req->getUserRef();
+ bool needConvertEndian = compareEndianWithOwn(clientRef);
+
// seize operation record
ndbrequire(signal->getLength() == CreateTrigReq::SignalLength + 1);
const Uint32 opKey = req->getOpKey();
@@ -12202,7 +12382,7 @@ Dbdict::execCREATE_TRIG_REQ(Signal* sign
// save name
SegmentedSectionPtr ssPtr;
signal->getSection(ssPtr, CreateTrigReq::TRIGGER_NAME_SECTION);
- SimplePropertiesSectionReader ssReader(ssPtr, getSectionSegmentPool());
+ SimplePropertiesSectionReader ssReader(ssPtr, getSectionSegmentPool(), needConvertEndian);
if (ssReader.getKey() != CreateTrigReq::TriggerNameKey ||
! ssReader.getString(opPtr.p->m_triggerName)) {
jam();
@@ -12648,9 +12828,16 @@ Dbdict::execDROP_TRIG_REQ(Signal* signal
OpDropTrigger opTmp;
opPtr.p=&opTmp;
+ /**
+ * Compare the endian of the client node and own node here
+ * to judge whether need convert endian.
+ */
+ const Uint32 clientRef = req->getUserRef();
+ bool needConvertEndian = compareEndianWithOwn(clientRef);
+
SegmentedSectionPtr ssPtr;
signal->getSection(ssPtr, DropTrigReq::TRIGGER_NAME_SECTION);
- SimplePropertiesSectionReader ssReader(ssPtr, getSectionSegmentPool());
+ SimplePropertiesSectionReader ssReader(ssPtr, getSectionSegmentPool(), needConvertEndian);
if (ssReader.getKey() != DropTrigReq::TriggerNameKey ||
! ssReader.getString(triggerName)) {
jam();
@@ -15448,11 +15635,18 @@ Dbdict::dropObj_abort_complete_done(Sign
void
Dbdict::create_fg_prepare_start(Signal* signal, SchemaOp* op){
/**
+ * Compare the endian of the client node and own node here
+ * to judge whether need convert endian.
+ */
+ const Uint32 clientRef = op->m_clientRef;
+ bool needConvertEndian = compareEndianWithOwn(clientRef);
+
+ /**
* Put data into table record
*/
SegmentedSectionPtr objInfoPtr;
getSection(objInfoPtr, ((OpCreateObj*)op)->m_obj_info_ptr_i);
- SimplePropertiesSectionReader it(objInfoPtr, getSectionSegmentPool());
+ SimplePropertiesSectionReader it(objInfoPtr, getSectionSegmentPool(), needConvertEndian);
Ptr<DictObject> obj_ptr; obj_ptr.setNull();
FilegroupPtr fg_ptr; fg_ptr.setNull();
@@ -15615,6 +15809,7 @@ Dbdict::create_fg_prepare_complete(Signa
ndbrequire(false);
}
+ // Send to own node, no need handle byte order.
sendSignal(ref, GSN_CREATE_FILEGROUP_REQ, signal, len, JBB);
}
@@ -15678,11 +15873,18 @@ Dbdict::create_fg_abort_complete(Signal*
void
Dbdict::create_file_prepare_start(Signal* signal, SchemaOp* op){
/**
+ * Compare the endian of the client node and own node here
+ * to judge whether need convert endian.
+ */
+ const Uint32 clientRef = op->m_clientRef;
+ bool needConvertEndian = compareEndianWithOwn(clientRef);
+
+ /**
* Put data into table record
*/
SegmentedSectionPtr objInfoPtr;
getSection(objInfoPtr, ((OpCreateObj*)op)->m_obj_info_ptr_i);
- SimplePropertiesSectionReader it(objInfoPtr, getSectionSegmentPool());
+ SimplePropertiesSectionReader it(objInfoPtr, getSectionSegmentPool(), needConvertEndian);
Ptr<DictObject> obj_ptr; obj_ptr.setNull();
FilePtr filePtr; filePtr.setNull();
@@ -15870,6 +16072,7 @@ Dbdict::create_file_prepare_complete(Sig
ndbrequire(false);
}
+ // Send to own node, no need to handle byte order.
char name[MAX_TAB_NAME_SIZE];
ConstRope tmp(c_rope_pool, f_ptr.p->m_path);
tmp.copy(name);
--- 1.55/storage/ndb/src/kernel/blocks/dblqh/Dblqh.hpp 2007-05-09 10:19:39 +08:00
+++ 1.56/storage/ndb/src/kernel/blocks/dblqh/Dblqh.hpp 2007-05-09 10:19:39 +08:00
@@ -2110,6 +2110,7 @@ private:
void execCHECK_LCP_STOP(Signal* signal);
void execSEND_PACKED(Signal* signal);
void execTUP_ATTRINFO(Signal* signal);
+ void execTUP_ORIG_ATTRINFO(Signal* signal);
void execREAD_CONFIG_REQ(Signal* signal);
void execLQHFRAGREQ(Signal* signal);
void execLQHADDATTREQ(Signal* signal);
@@ -2392,6 +2393,7 @@ private:
void systemErrorLab(Signal* signal, int line);
void initFourth(Signal* signal);
void packLqhkeyreqLab(Signal* signal);
+ void copyAttrInfo(Signal* signal);
void sendNdbSttorryLab(Signal* signal);
void execSrCompletedLab(Signal* signal);
void execLogRecord(Signal* signal);
@@ -2574,6 +2576,9 @@ private:
void acckeyconf_tupkeyreq(Signal*, TcConnectionrec*, Fragrecord*, Uint32, Uint32);
void acckeyconf_load_diskpage(Signal*,TcConnectionrecPtr,Fragrecord*,Uint32);
+ void Dblqh::copy_keydata_cache_to_linear(Signal* signal);
+ void Dblqh::copy_keydata_linear_to_cache(Signal* signal);
+ bool handle_keydata_endian_conversion(Signal* signal);
void handle_nr_copy(Signal*, Ptr<TcConnectionrec>);
void exec_acckeyreq(Signal*, Ptr<TcConnectionrec>);
int compare_key(const TcConnectionrec*, const Uint32 * ptr, Uint32 len);
@@ -2887,6 +2892,21 @@ private:
Uint32 c_diskless;
Uint32 c_error_insert_table_id;
+
+/* ------------------------------------------------------------------------- */
+/* THIS VARIABLE IS COPIED FROM DBTUP. */
+/* IT IS USED TO STORE THE ORIGINAL NOT INTERPRETED ATTRINFO WHEN THE */
+/* ENDIAN OF API NODE AND DBLQH NODE ARE DIFFERENT, IN THIS CASE, THE */
+/* REGTCPTR WILL STORE THE INTERPRETED ATTRINFO COME FROM DBTUP, AND */
+/* ENSURE THAT THE REDO-LOGS WILL BE WRITTEN CORRECTLY. THEN WE CAN */
+/* USE THIS BUFFER TO SEND THE ORIGINAL ATTRINFO TO THE NEXT DBLQH */
+/* BLOCK, AND ENSURE THE UPDATE OPERATION ON NEXT REPLICA IS CORRECT. */
+/* ------------------------------------------------------------------------- */
+// A little bit bigger to cover overwrites in copy algorithms (16384 real size).
+#define ZATTR_BUFFER_SIZE 16384
+ Uint32 caiBuffer[ZATTR_BUFFER_SIZE + 16];
+ // Store the current length of ATTRINFO in caiBuffer.
+ Uint32 caiLen;
public:
bool is_same_trans(Uint32 opId, Uint32 trid1, Uint32 trid2);
--- 1.21/storage/ndb/src/kernel/blocks/dblqh/DblqhInit.cpp 2007-05-09 10:19:39 +08:00
+++ 1.22/storage/ndb/src/kernel/blocks/dblqh/DblqhInit.cpp 2007-05-09 10:19:39 +08:00
@@ -208,6 +208,7 @@ Dblqh::Dblqh(Block_context& ctx):
addRecSignal(GSN_CHECK_LCP_STOP, &Dblqh::execCHECK_LCP_STOP);
addRecSignal(GSN_SEND_PACKED, &Dblqh::execSEND_PACKED);
addRecSignal(GSN_TUP_ATTRINFO, &Dblqh::execTUP_ATTRINFO);
+ addRecSignal(GSN_TUP_ORIG_ATTRINFO, &Dblqh::execTUP_ORIG_ATTRINFO);
addRecSignal(GSN_READ_CONFIG_REQ, &Dblqh::execREAD_CONFIG_REQ, true);
addRecSignal(GSN_LQHFRAGREQ, &Dblqh::execLQHFRAGREQ);
addRecSignal(GSN_LQHADDATTREQ, &Dblqh::execLQHADDATTREQ);
--- 1.127/storage/ndb/src/kernel/blocks/dblqh/DblqhMain.cpp 2007-05-09 10:19:39 +08:00
+++ 1.128/storage/ndb/src/kernel/blocks/dblqh/DblqhMain.cpp 2007-05-09 10:19:39 +08:00
@@ -2960,6 +2960,10 @@ Dblqh::receive_keyinfo(Signal* signal,
fragptr = regFragptr;
endgettupkeyLab(signal);
}
+ /**
+ * The handle of KEYINFO for SCAN_FRAGREQ is in DBTUX.
+ * see Dbtux::execTUX_BOUND_INFO().
+ */
return;
}//Dblqh::execKEYINFO()
@@ -3134,6 +3138,27 @@ void Dblqh::execTUP_ATTRINFO(Signal* sig
}//if
}//Dblqh::execTUP_ATTRINFO()
+/* ************************************************************************>> */
+/* TUP_ORIG_ATTRINFO: Interpreted execution in DBTUP generates attr info */
+/* which is sent back to DBLQH for sending to the next replica. */
+/* This signal is sent while the endian of API node and DBTUP node(own node) */
+/* are different. */
+/* ************************************************************************>> */
+void Dblqh::execTUP_ORIG_ATTRINFO(Signal* signal)
+{
+ TcConnectionrec *regTcConnectionrec = tcConnectionrec;
+ Uint32 length = signal->length() - 3;
+ Uint32 tcIndex = signal->theData[0];
+ Uint32 ttcConnectrecFileSize = ctcConnectrecFileSize;
+ jamEntry();
+ tcConnectptr.i = tcIndex;
+ ptrCheckGuard(tcConnectptr, ttcConnectrecFileSize, regTcConnectionrec);
+ ndbrequire(tcConnectptr.p->transactionState == TcConnectionrec::WAIT_TUP);
+ Uint32 *dataPtr = &signal->theData[3];
+ MEMCOPY_NO_WORDS(&caiBuffer[caiLen], dataPtr, length);
+ caiLen = caiLen + length;
+}//Dblqh::execTUP_ORIG_ATTRINFO()
+
/* ------------------------------------------------------------------------- */
/* ------- HANDLE ATTRINFO FROM LQH ------- */
/* */
@@ -3143,16 +3168,34 @@ void Dblqh::lqhAttrinfoLab(Signal* signa
TcConnectionrec * const regTcPtr = tcConnectptr.p;
if (regTcPtr->operation != ZREAD) {
if (regTcPtr->opExec != 1) {
- if (saveTupattrbuf(signal, dataPtr, length) == ZOK) {
- ;
- } else {
- jam();
+ /**
+ * Compare the endian of API node and OWN node here.
+ * If they are different, we will not store the ATTRINFO for REDO log
+ * here, and will wait for the TUP_ATTRINFO signal from DBTUP block
+ * to get the ATTRINFO whose byte order has been handled in DBTUP block.
+ * Otherwise, we will store the ATTRINFO for logging the REDO log here,
+ * thus can save TUP_ATTRINFO signal.
+ */
+ const Uint32 apiBlockRef= regTcPtr->applRef;
+ bool needConvertEndian = compareEndianWithOwn(apiBlockRef);
+
+ if (!needConvertEndian) {
+ // no need convert endian
+ if (saveTupattrbuf(signal, dataPtr, length) == ZOK) {
+ ;
+ } else {
+ jam();
/* ------------------------------------------------------------------------- */
/* WE MIGHT BE WAITING FOR RESPONSE FROM SOME BLOCK HERE. THUS WE NEED TO */
/* GO THROUGH THE STATE MACHINE FOR THE OPERATION. */
/* ------------------------------------------------------------------------- */
- localAbortStateHandlerLab(signal);
- return;
+ localAbortStateHandlerLab(signal);
+ return;
+ }//if
+ } else {
+ // need convert endian
+ MEMCOPY_NO_WORDS(&caiBuffer[caiLen], dataPtr, length);
+ caiLen = caiLen + length;
}//if
}//if
}//if
@@ -3199,11 +3242,24 @@ int Dblqh::findTransaction(UintR Transid
int Dblqh::saveTupattrbuf(Signal* signal, Uint32* dataPtr, Uint32 len)
{
TcConnectionrec * const regTcPtr = tcConnectptr.p;
+
+ /**
+ * Save into regTcPtr->firstAttrinfo[] first.
+ */
+ Uint32 currTupAiLen = regTcPtr->currTupAiLen;
+ Uint32 lqhLen = regTcPtr->reclenAiLqhkey;
+ if (lqhLen > 0 && currTupAiLen == 0) {
+ MEMCOPY_NO_WORDS(®TcPtr->firstAttrinfo[0], dataPtr, lqhLen);
+ regTcPtr->currTupAiLen = currTupAiLen + lqhLen;
+ len -= lqhLen;
+ dataPtr += lqhLen;
+ }
+
while(len)
{
Uint32 length = len > AttrInfo::DataLength ? AttrInfo::DataLength : len;
Uint32 tfirstfreeAttrinbuf = cfirstfreeAttrinbuf;
- Uint32 currTupAiLen = regTcPtr->currTupAiLen;
+ currTupAiLen = regTcPtr->currTupAiLen;
if (tfirstfreeAttrinbuf == RNIL) {
jam();
terrorCode = ZGET_ATTRINBUF_ERROR;
@@ -3390,6 +3446,17 @@ void Dblqh::execLQHKEYREQ(Signal* signal
regTcPtr->transid[1] = sig2;
regTcPtr->applRef = sig3;
regTcPtr->applOprec = sig4;
+ /**
+ * Fixed for WL#3615.
+ */
+ if ((LqhKeyReq::getApplicationAddressFlag(Treqinfo) == 0) &&
+ (LqhKeyReq::getSameClientAndTcFlag(Treqinfo) == 0)) {
+ /**
+ * lqhKeyReq->variableData[0] is replaced by other data
+ * set applRef to regTcPtr->clientBlockref, ie. the sender.
+ */
+ regTcPtr->applRef = regTcPtr->clientBlockref;
+ }
regTcPtr->commitAckMarker = RNIL;
if(LqhKeyReq::getMarkerFlag(Treqinfo)){
@@ -3633,6 +3700,8 @@ void Dblqh::execLQHKEYREQ(Signal* signal
}//if
LQHKEY_error(signal, 1);
}//if
+ // initialize caiLen
+ caiLen = 0;
if (TreclenAiLqhkey != 0) {
if (regTcPtr->operation != ZREAD) {
if (regTcPtr->operation != ZDELETE) {
@@ -3651,18 +3720,39 @@ void Dblqh::execLQHKEYREQ(Signal* signal
/* READS AND DELETES CAN ONLY HAVE INFORMATION ABOUT WHAT IS TO BE READ. */
/* NO INFORMATION THAT NEEDS LOGGING. */
/*---------------------------------------------------------------------------*/
- sig0 = lqhKeyReq->variableData[nextPos + 0];
- sig1 = lqhKeyReq->variableData[nextPos + 1];
- sig2 = lqhKeyReq->variableData[nextPos + 2];
- sig3 = lqhKeyReq->variableData[nextPos + 3];
- sig4 = lqhKeyReq->variableData[nextPos + 4];
-
- regTcPtr->firstAttrinfo[0] = sig0;
- regTcPtr->firstAttrinfo[1] = sig1;
- regTcPtr->firstAttrinfo[2] = sig2;
- regTcPtr->firstAttrinfo[3] = sig3;
- regTcPtr->firstAttrinfo[4] = sig4;
- regTcPtr->currTupAiLen = TreclenAiLqhkey;
+
+ /**
+ * Compare the endian of API node and OWN node here.
+ *
+ * If they are different, we will store the original ATTRINFO into a
+ * buffer, then use it to send the original ATTRINFO to the next DBLQH
+ * block. And we will wait for the TUP_ATTRINFO signal from DBTUP block,
+ * it will contain the byter order handled ATTRINFO, and we will store
+ * this ATTRINFO into the regTcPtr cache, and use it to log into REDO-log.
+ *
+ * Otherwise, we will store the original ATTRINFO into regTcPtr cache,
+ * and use it to send to next DBLQH block and log into REDO-log.
+ */
+ const Uint32 apiBlockRef= regTcPtr->applRef;
+ bool needConvertEndian = compareEndianWithOwn(apiBlockRef);
+
+ if (!needConvertEndian) {
+ sig0 = lqhKeyReq->variableData[nextPos + 0];
+ sig1 = lqhKeyReq->variableData[nextPos + 1];
+ sig2 = lqhKeyReq->variableData[nextPos + 2];
+ sig3 = lqhKeyReq->variableData[nextPos + 3];
+ sig4 = lqhKeyReq->variableData[nextPos + 4];
+
+ regTcPtr->firstAttrinfo[0] = sig0;
+ regTcPtr->firstAttrinfo[1] = sig1;
+ regTcPtr->firstAttrinfo[2] = sig2;
+ regTcPtr->firstAttrinfo[3] = sig3;
+ regTcPtr->firstAttrinfo[4] = sig4;
+ regTcPtr->currTupAiLen = TreclenAiLqhkey;
+ } else {
+ MEMCOPY_NO_WORDS(&caiBuffer[0], lqhKeyReq->variableData+nextPos, TreclenAiLqhkey);
+ caiLen = TreclenAiLqhkey;
+ }//if
} else {
jam();
regTcPtr->reclenAiLqhkey = 0;
@@ -3715,6 +3805,21 @@ void Dblqh::endgettupkeyLab(Signal* sign
regTcPtr->transactionState = TcConnectionrec::WAIT_ATTR;
return;
}//if
+
+ /**
+ * Now handle the endian conversion for key data.
+ * If the endian of sender and receiver are different while
+ * sending LQHKEYREQ signal, the byte order of the key data
+ * will be swapped after LQHKEYREQ signal is received, so we
+ * must turn them back again.
+ */
+ bool ok = handle_keydata_endian_conversion(signal);
+ if (unlikely(!ok))
+ {
+ jam();
+ ndbrequire(false);
+ return;
+ }
/* ---------------------------------------------------------------------- */
/* NOW RECEPTION OF LQHKEYREQ IS COMPLETED THE NEXT STEP IS TO START*/
@@ -3756,6 +3861,130 @@ void Dblqh::endgettupkeyLab(Signal* sign
return;
}//Dblqh::endgettupkeyLab()
+/*
+ * Copy the the KEY data from data buffer to a linear buffer,
+ * in order to handle endian for all the KEY data.
+ */
+void Dblqh::copy_keydata_cache_to_linear(Signal* signal)
+{
+ DatabufPtr regDatabufptr;
+ UintR Ti;
+ UintR Tdata0;
+ UintR Tdata1;
+ UintR Tdata2;
+ UintR Tdata3;
+ UintR* Tdata32;
+
+ TcConnectionrec * const regTcPtr = tcConnectptr.p;
+ Tdata32 = signal->theData;
+
+ Tdata0 = regTcPtr->tupkeyData[0];
+ Tdata1 = regTcPtr->tupkeyData[1];
+ Tdata2 = regTcPtr->tupkeyData[2];
+ Tdata3 = regTcPtr->tupkeyData[3];
+ Tdata32[0] = Tdata0;
+ Tdata32[1] = Tdata1;
+ Tdata32[2] = Tdata2;
+ Tdata32[3] = Tdata3;
+
+ if (regTcPtr->primKeyLen > 4) {
+ regDatabufptr.i = regTcPtr->firstTupkeybuf;
+ Ti = 4;
+ while (regDatabufptr.i != RNIL) {
+ ptrCheckGuard(regDatabufptr, cdatabufFileSize, databuf);
+ Tdata0 = regDatabufptr.p->data[0];
+ Tdata1 = regDatabufptr.p->data[1];
+ Tdata2 = regDatabufptr.p->data[2];
+ Tdata3 = regDatabufptr.p->data[3];
+ Tdata32[Ti + 0] = Tdata0;
+ Tdata32[Ti + 1] = Tdata1;
+ Tdata32[Ti + 2] = Tdata2;
+ Tdata32[Ti + 3] = Tdata3;
+ regDatabufptr.i = regDatabufptr.p->nextDatabuf;
+ Ti += 4;
+ }//while
+ }//if
+}
+
+/*
+ * Copy the the KEY data from the linear buffer back to the data buffer
+ * after handled endian for all the KEY data.
+ */
+void Dblqh::copy_keydata_linear_to_cache(Signal* signal)
+{
+ DatabufPtr regDatabufptr;
+ UintR Ti;
+ UintR Tdata0;
+ UintR Tdata1;
+ UintR Tdata2;
+ UintR Tdata3;
+ UintR* Tdata32;
+
+ TcConnectionrec * const regTcPtr = tcConnectptr.p;
+ Tdata32 = signal->theData;
+
+ Tdata0 = Tdata32[0];
+ Tdata1 = Tdata32[1];
+ Tdata2 = Tdata32[2];
+ Tdata3 = Tdata32[3];
+ regTcPtr->tupkeyData[0] = Tdata0;
+ regTcPtr->tupkeyData[1] = Tdata1;
+ regTcPtr->tupkeyData[2] = Tdata2;
+ regTcPtr->tupkeyData[3] = Tdata3;
+
+ if (regTcPtr->primKeyLen > 4) {
+ regDatabufptr.i = regTcPtr->firstTupkeybuf;
+ Ti = 4;
+ while (regDatabufptr.i != RNIL) {
+ ptrCheckGuard(regDatabufptr, cdatabufFileSize, databuf);
+ Tdata0 = Tdata32[Ti + 0];
+ Tdata1 = Tdata32[Ti + 1];
+ Tdata2 = Tdata32[Ti + 2];
+ Tdata3 = Tdata32[Ti + 3];
+ regDatabufptr.p->data[0] = Tdata0;
+ regDatabufptr.p->data[1] = Tdata1;
+ regDatabufptr.p->data[2] = Tdata2;
+ regDatabufptr.p->data[3] = Tdata3;
+ regDatabufptr.i = regDatabufptr.p->nextDatabuf;
+ Ti += 4;
+ }//while
+ }//if
+}
+
+/*
+ * Handle endian for all the KEY data.
+ * We compare the endian of the SENDER node and OWN node here,
+ * if they are different, then should handle endian for the
+ * KEY data, because they have been converted while receiving
+ * signal.
+ */
+bool
+Dblqh::handle_keydata_endian_conversion(Signal* signal)
+{
+ const Uint32 senderBlockRef = signal->senderBlockRef();
+ bool needConvertEndian = compareEndianWithOwn(senderBlockRef);
+
+ if (needConvertEndian)
+ {
+ jam();
+
+ copy_keydata_cache_to_linear(signal);
+
+ Uint32 tabPtr = fragptr.p->tabRef;
+ Uint32 *src = signal->theData;
+
+ bool ok = convert_endian_key(tabPtr, src);
+ if (unlikely(!ok))
+ {
+ return false;
+ }
+
+ copy_keydata_linear_to_cache(signal);
+ }//if
+
+ return true; // success
+}
+
void Dblqh::prepareContinueAfterBlockedLab(Signal* signal)
{
UintR ttcScanOp;
@@ -3841,7 +4070,7 @@ void Dblqh::prepareContinueAfterBlockedL
TRACENR(" rowid: " << regTcPtr->m_row_id);
TRACENR(" key: " << regTcPtr->tupkeyData[0]);
}
-
+
if (likely(activeCreat == Fragrecord::AC_NORMAL))
{
if (TRACENR_FLAG)
@@ -3915,6 +4144,7 @@ Dblqh::exec_acckeyreq(Signal* signal, Tc
if (regTcPtr.p->primKeyLen > 4) {
sendKeyinfoAcc(signal, 11);
}//if
+
EXECUTE_DIRECT(refToBlock(regTcPtr.p->tcAccBlockref), GSN_ACCKEYREQ,
signal, 7 + regTcPtr.p->primKeyLen);
if (signal->theData[0] < RNIL) {
@@ -3929,7 +4159,7 @@ Dblqh::exec_acckeyreq(Signal* signal, Tc
execACCKEYREF(signal);
}//if
return;
-}//Dblqh::prepareContinueAfterBlockedLab()
+}//Dblqh::exec_acckeyreq()
void
Dblqh::handle_nr_copy(Signal* signal, Ptr<TcConnectionrec> regTcPtr)
@@ -4377,7 +4607,7 @@ Dblqh::readPrimaryKeys(Uint32 opPtrI, Ui
Uint32 keyPartLen[MAX_ATTRIBUTES_IN_INDEX];
return xfrm_key(tableId, (Uint32*)Tmp, dst, ~0, keyPartLen);
}
-
+
return keyLen;
}
@@ -5270,6 +5500,18 @@ void Dblqh::packLqhkeyreqLab(Signal* sig
BlockReference lqhRef = calcLqhBlockRef(regTcPtr->nextReplica);
+ /**
+ * Compare the endian of API node and OWN node here.
+ * If they are different, copy the stored original ATTRINFO in buffer
+ * into regTcPtr cache then send to the next DBLQH block.
+ */
+ const Uint32 apiBlockRef = regTcPtr->applRef;
+ bool needConvertEndian = compareEndianWithOwn(apiBlockRef);
+
+ if (needConvertEndian) {
+ copyAttrInfo(signal);
+ }//if
+
if (likely(nextPos + TAiLen + LqhKeyReq::FixedSignalLength <= 25))
{
jam();
@@ -5376,6 +5618,51 @@ void Dblqh::packLqhkeyreqLab(Signal* sig
releaseOprec(signal);
}//Dblqh::packLqhkeyreqLab()
+/* ------------------------------------------------------------------------- */
+/* COPY ATTRINFO FROM CAIBUFFER INTO REGTCPTR CACHE, SO THAT CAN SEND IT TO */
+/* THE NEXT REPLICA. */
+/* ------------------------------------------------------------------------- */
+void Dblqh::copyAttrInfo(Signal* signal)
+{
+ TcConnectionrec * const regTcPtr = tcConnectptr.p;
+
+/* ---- RELEASE ATTRINFO BUFFERS ------------------- */
+ AttrbufPtr regAttrinbufptr;
+ regAttrinbufptr.i = regTcPtr->firstAttrinbuf;
+ while (regAttrinbufptr.i != RNIL) {
+ jam();
+ regAttrinbufptr.i= release_attrinbuf(regAttrinbufptr.i);
+ }//while
+ regTcPtr->firstAttrinbuf = RNIL;
+ regTcPtr->lastAttrinbuf = RNIL;
+
+/* ---- DO SOME INITIALIZATION ------------------- */
+ regTcPtr->currTupAiLen = 0;
+
+/* ---- COPY FIRSTATTRINFO ------------------- */
+ Uint32 lqhLen = regTcPtr->reclenAiLqhkey;
+ ndbrequire(caiLen >= lqhLen);
+ if (lqhLen > 0) {
+ MEMCOPY_NO_WORDS(®TcPtr->firstAttrinfo[0], &caiBuffer[0], lqhLen);
+ regTcPtr->currTupAiLen = lqhLen;
+ }//if
+
+/* ---- COPY ATTRBUF ------------------- */
+ UintR TotReclenAi = regTcPtr->totSendlenAi;
+ ndbrequire(caiLen >= TotReclenAi);
+ Uint32 length = TotReclenAi - lqhLen;
+ if (saveTupattrbuf(signal, &caiBuffer[lqhLen], length) == ZOK) {
+ return;
+ } else {
+ jam();
+/* ------------------------------------------------------------------------- */
+/* WE MIGHT BE WAITING FOR RESPONSE FROM SOME BLOCK HERE. THUS WE NEED TO */
+/* GO THROUGH THE STATE MACHINE FOR THE OPERATION. */
+/* ------------------------------------------------------------------------- */
+ localAbortStateHandlerLab(signal);
+ }//if
+}
+
/* ========================================================================= */
/* ==== CHECK IF THE LOG RECORD FITS INTO THE CURRENT MBYTE, ======= */
/* OTHERWISE SWITCH TO NEXT MBYTE. */
@@ -6347,6 +6634,7 @@ void Dblqh::commitContinueAfterBlockedLa
tupCommitReq->opPtr = sig0;
tupCommitReq->gci = regTcPtr.p->gci;
tupCommitReq->hashValue = regTcPtr.p->hashValue;
+ tupCommitReq->applRef = regTcPtr.p->applRef;
EXECUTE_DIRECT(tup, GSN_TUP_COMMITREQ, signal,
TupCommitReq::SignalLength);
@@ -8561,6 +8849,7 @@ void Dblqh::accScanConfScanLab(Signal* s
req->errorCode = RNIL;
req->tuxScanPtrI = scanptr.p->scanAccPtr;
Uint32 len = req->boundAiLength = copy_bounds(req->data, tcConnectptr.p);
+ req->scanApiBlockref = scanptr.p->scanApiBlockref;
EXECUTE_DIRECT(DBTUX, GSN_TUX_BOUND_INFO, signal,
TuxBoundInfo::SignalLength + len);
@@ -9139,7 +9428,14 @@ Dblqh::readPrimaryKeys(ScanRecord *scanP
tableId = tFragPtr.p->tabRef;
}
+ /**
+ * Set capiBlockref variable member to scanP->scanApiBlockref,
+ * so that we can use it to judge the endian of the API node while reading key data.
+ */
+ c_tup->capiBlockref = scanP->scanApiBlockref;
int ret = c_tup->accReadPk(tableId, fragId, fragPageId, pageIndex, dst, false);
+ // Set c_tup->capiBlockref to 0, in case use it later.
+ c_tup->capiBlockref = 0;
jamEntry();
if(0)
ndbout_c("readPrimaryKeys(table: %d fragment: %d [ %d %d ] -> %d",
@@ -9766,6 +10062,13 @@ Uint32 Dblqh::sendKeyinfo20(Signal* sign
ScanRecord * scanP,
TcConnectionrec * tcConP)
{
+ /**
+ * send keyinfo from DB node to API node,
+ * so it is needed to handle the byte order of the key data if the
+ * endian of the DB node and API node are different.
+ * this is implemented by readPrimaryKeys() transfering the apiBlockref to
+ * Dbtup::readAttributes().
+ */
ndbrequire(scanP->m_curr_batch_size_rows < MAX_PARALLEL_OP_PER_SCAN);
KeyInfo20 * keyInfo = (KeyInfo20 *)&signal->theData[0];
--- 1.42/storage/ndb/src/kernel/blocks/dbtc/Dbtc.hpp 2007-05-09 10:19:39 +08:00
+++ 1.43/storage/ndb/src/kernel/blocks/dbtc/Dbtc.hpp 2007-05-09 10:19:39 +08:00
@@ -1597,6 +1597,9 @@ private:
void wrongSchemaVersionErrorLab(Signal* signal);
void noFreeConnectionErrorLab(Signal* signal);
void tckeyreq050Lab(Signal* signal);
+ void copy_keydata_cache_to_linear(Signal* signal);
+ void copy_keydata_linear_to_cache(Signal* signal);
+ bool handle_keydata_endian_conversion(Signal* signal);
void timeOutFoundLab(Signal* signal, UintR anAdd, Uint32 errCode);
void completeTransAtTakeOverLab(Signal* signal, UintR TtakeOverInd);
void completeTransAtTakeOverDoLast(Signal* signal, UintR TtakeOverInd);
--- 1.125/storage/ndb/src/kernel/blocks/dbtc/DbtcMain.cpp 2007-05-09 10:19:39 +08:00
+++ 1.126/storage/ndb/src/kernel/blocks/dbtc/DbtcMain.cpp 2007-05-09 10:19:39 +08:00
@@ -1882,6 +1882,10 @@ void Dbtc::execKEYINFO(Signal* signal)
}//if
} else {
jam();
+ /**
+ * The handle of KEYINFO for SCAN_TABREQ is in DBTUX.
+ * see Dbtux::execTUX_BOUND_INFO().
+ */
return;
}//if
} while (1);
@@ -2774,6 +2778,7 @@ void Dbtc::execTCKEYREQ(Signal* signal)
regCachePtr->keydata[3] = Tdata4;
TkeyLength = tcKeyReq->getKeyLength(Treqinfo);
+
Uint32 TAIDataIndex;
if (TkeyLength > 8) {
TAIDataIndex = TkeyIndex + 8;
@@ -2879,6 +2884,10 @@ void Dbtc::execTCKEYREQ(Signal* signal)
regApiPtr->apiConnectstate = CS_RECEIVING;
}//if
}//if
+
+ // set treqinfo, so that can use it in sendlqhkeyreq().
+ treqinfo = Treqinfo;
+
if (TkeyLength <= 4) {
tckeyreq050Lab(signal);
return;
@@ -2928,6 +2937,20 @@ void Dbtc::tckeyreq050Lab(Signal* signal
terrorCode = 0;
+ /**
+ * Now handle the endian conversion for key data.
+ * If the endian of sender and receiver are different while
+ * sending TCKEYREQ/KEYINFO signal, the byte order of the key data
+ * will be swapped after TCKEYREQ signal is received, so we
+ * must turn them back again.
+ */
+ bool ok = handle_keydata_endian_conversion(signal);
+ if (unlikely(!ok))
+ {
+ releaseAtErrorLab(signal);
+ return;
+ }
+
hash(signal); /* NOW IT IS TIME TO CALCULATE THE HASH VALUE*/
if (unlikely(terrorCode))
@@ -3102,6 +3125,146 @@ void Dbtc::tckeyreq050Lab(Signal* signal
return;
}//Dbtc::tckeyreq050Lab()
+/*
+ * Copy the the KEY data from data buffer to a linear buffer.
+ * So that can handle endian for all the KEY data.
+ */
+void Dbtc::copy_keydata_cache_to_linear(Signal* signal)
+{
+ DatabufRecordPtr locDatabufptr;
+ UintR Ti;
+ UintR Tdata0;
+ UintR Tdata1;
+ UintR Tdata2;
+ UintR Tdata3;
+ UintR* Tdata32;
+
+ CacheRecord * const regCachePtr = cachePtr.p;
+ Tdata32 = signal->theData;
+
+ Tdata0 = regCachePtr->keydata[0];
+ Tdata1 = regCachePtr->keydata[1];
+ Tdata2 = regCachePtr->keydata[2];
+ Tdata3 = regCachePtr->keydata[3];
+ Tdata32[0] = Tdata0;
+ Tdata32[1] = Tdata1;
+ Tdata32[2] = Tdata2;
+ Tdata32[3] = Tdata3;
+
+ if (regCachePtr->keylen > 4) {
+ locDatabufptr.i = regCachePtr->firstKeybuf;
+ Ti = 4;
+ while (locDatabufptr.i != RNIL) {
+ ptrCheckGuard(locDatabufptr, cdatabufFilesize, databufRecord);
+ Tdata0 = locDatabufptr.p->data[0];
+ Tdata1 = locDatabufptr.p->data[1];
+ Tdata2 = locDatabufptr.p->data[2];
+ Tdata3 = locDatabufptr.p->data[3];
+ Tdata32[Ti + 0] = Tdata0;
+ Tdata32[Ti + 1] = Tdata1;
+ Tdata32[Ti + 2] = Tdata2;
+ Tdata32[Ti + 3] = Tdata3;
+ locDatabufptr.i = locDatabufptr.p->nextDatabuf;
+ Ti += 4;
+ }//while
+ }//if
+}
+
+/*
+ * Copy the the KEY data from the linear buffer back to the data buffer
+ * after handled endian for all the KEY data.
+ */
+void Dbtc::copy_keydata_linear_to_cache(Signal* signal)
+{
+ DatabufRecordPtr locDatabufptr;
+ UintR Ti;
+ UintR Tdata0;
+ UintR Tdata1;
+ UintR Tdata2;
+ UintR Tdata3;
+ UintR* Tdata32;
+
+ CacheRecord * const regCachePtr = cachePtr.p;
+ Tdata32 = signal->theData;
+
+ Tdata0 = Tdata32[0];
+ Tdata1 = Tdata32[1];
+ Tdata2 = Tdata32[2];
+ Tdata3 = Tdata32[3];
+ regCachePtr->keydata[0] = Tdata0;
+ regCachePtr->keydata[1] = Tdata1;
+ regCachePtr->keydata[2] = Tdata2;
+ regCachePtr->keydata[3] = Tdata3;
+
+ if (regCachePtr->keylen > 4) {
+ locDatabufptr.i = regCachePtr->firstKeybuf;
+ Ti = 4;
+ while (locDatabufptr.i != RNIL) {
+ ptrCheckGuard(locDatabufptr, cdatabufFilesize, databufRecord);
+ Tdata0 = Tdata32[Ti + 0];
+ Tdata1 = Tdata32[Ti + 1];
+ Tdata2 = Tdata32[Ti + 2];
+ Tdata3 = Tdata32[Ti + 3];
+ locDatabufptr.p->data[0] = Tdata0;
+ locDatabufptr.p->data[1] = Tdata1;
+ locDatabufptr.p->data[2] = Tdata2;
+ locDatabufptr.p->data[3] = Tdata3;
+ locDatabufptr.i = locDatabufptr.p->nextDatabuf;
+ Ti += 4;
+ }//while
+ }//if
+}
+
+/*
+ * Handle endian for all the KEY data.
+ * We compare the endian of the SENDER node and OWN node here,
+ * if they are different, then should handle endian for the
+ * KEY data, because they have been converted while receiving
+ * signal.
+ */
+bool
+Dbtc::handle_keydata_endian_conversion(Signal* signal)
+{
+ TcConnectRecord * const regTcPtr = tcConnectptr.p;
+ ApiConnectRecord * const regApiPtr = apiConnectptr.p;
+ bool needConvertEndian;
+ /**
+ * For index operation, API will send TCINDXREQ to DBTC, then
+ * DBTC will collect the KEY data and execute TCKEYREQ signal
+ * directly. Thus we should compare the endian of OWN node
+ * with API node in this case.
+ */
+ if (regTcPtr->isIndexOp == 2) {
+ const Uint32 apiBlockRef = regApiPtr->ndbapiBlockref;
+ needConvertEndian = compareEndianWithOwn(apiBlockRef);
+ } else {
+ const Uint32 senderBlockRef = signal->senderBlockRef();
+ needConvertEndian = compareEndianWithOwn(senderBlockRef);
+ }
+
+ if (needConvertEndian)
+ {
+ jam();
+
+ copy_keydata_cache_to_linear(signal);
+
+ CacheRecord * const regCachePtr = cachePtr.p;
+ Uint32 tabPtrI = regCachePtr->tableref;
+ Uint32 *src = signal->theData;
+
+ bool ok = convert_endian_key(tabPtrI, src);
+ if (unlikely(!ok))
+ {
+ terrorCode = ZINVALID_KEY;
+ return false;
+ }
+
+ copy_keydata_linear_to_cache(signal);
+ }
+
+ return true; // success
+}
+
void Dbtc::attrinfoDihReceivedLab(Signal* signal)
{
CacheRecord * const regCachePtr = cachePtr.p;
@@ -3258,7 +3421,14 @@ void Dbtc::sendlqhkeyreq(Signal* signal,
sig1 = regCachePtr->fragmentid + (regTcPtr->tcNodedata[1] << 16);
sig2 = regApiPtr->transid[0];
sig3 = regApiPtr->transid[1];
- sig4 = (regTcPtr->isIndexOp == 2) ? reference() : regApiPtr->ndbapiBlockref;
+ /**
+ * Insert or Delete from index table will execute TCKEYREQ signal directly,
+ * so set sig4 to local node here.
+ */
+ sig4 = ((regTcPtr->isIndexOp == 2) ||
+ (TcKeyReq::getExecutingTrigger(treqinfo))) ? reference() : regApiPtr->ndbapiBlockref;
+ //ndbout_c("the API node is: %u", refToNode(sig4));
+ treqinfo = 0;
sig5 = regTcPtr->clientData;
sig6 = regCachePtr->scanInfo;
--- 1.50/storage/ndb/src/kernel/blocks/dbtup/Dbtup.hpp 2007-05-09 10:19:39 +08:00
+++ 1.51/storage/ndb/src/kernel/blocks/dbtup/Dbtup.hpp 2007-05-09 10:19:39 +08:00
@@ -280,6 +280,7 @@ public:
Tsman* c_tsman;
Lgman* c_lgman;
Page_cache_client m_pgman;
+ BlockReference capiBlockref;
// State values
enum ChangeMaskState {
@@ -1756,6 +1757,12 @@ private:
//------------------------------------------------------------------
//------------------------------------------------------------------
+ void sendOrigAttrinfo(Signal* signal,
+ Uint32 TlogSize,
+ Operationrec * regOperPtr);
+
+//------------------------------------------------------------------
+//------------------------------------------------------------------
void sendTUPKEYCONF(Signal* signal,
KeyReqStruct *req_struct,
Operationrec * regOperPtr);
@@ -1961,6 +1968,7 @@ private:
bool readDiskBitsNotNULL(Uint32*, KeyReqStruct*, AttributeHeader*, Uint32);
bool updateDiskBitsNULLable(Uint32*, KeyReqStruct*, Uint32);
bool updateDiskBitsNotNULL(Uint32*, KeyReqStruct*, Uint32);
+ void swapFixedSizeAttr(Uint32* attrBuffer, Uint32 attrDescriptor, Uint32 attrNoOfWords);
//------------------------------------------------------------------
@@ -2562,6 +2570,8 @@ private:
// A little bit bigger to cover overwrites in copy algorithms (16384 real size).
#define ZATTR_BUFFER_SIZE 16384
Uint32 clogMemBuffer[ZATTR_BUFFER_SIZE + 16];
+ // Used to store the interpreted ATTRINFO to send to DBLQH
+ Uint32 caiBuffer[ZATTR_BUFFER_SIZE + 16];
Uint32 coutBuffer[ZATTR_BUFFER_SIZE + 16];
Uint32 cinBuffer[ZATTR_BUFFER_SIZE + 16];
Uint32 ctemp_page[ZWORDS_ON_PAGE];
--- 1.17/storage/ndb/src/kernel/blocks/dbtup/DbtupCommit.cpp 2007-05-09 10:19:39 +08:00
+++ 1.18/storage/ndb/src/kernel/blocks/dbtup/DbtupCommit.cpp 2007-05-09 10:19:39 +08:00
@@ -435,6 +435,8 @@ void Dbtup::execTUP_COMMITREQ(Signal* si
OperationrecPtr regOperPtr;
TablerecPtr regTabPtr;
KeyReqStruct req_struct;
+ // initialize rec_blockref in case use it later
+ req_struct.rec_blockref= 0;
TransState trans_state;
Uint32 no_of_fragrec, no_of_tablerec, hash_value, gci;
@@ -469,6 +471,7 @@ void Dbtup::execTUP_COMMITREQ(Signal* si
req_struct.signal= signal;
req_struct.hash_value= hash_value;
req_struct.gci= gci;
+ req_struct.rec_blockref= tupCommitReq->applRef;
ptrCheckGuard(regTabPtr, no_of_tablerec, tablerec);
--- 1.47/storage/ndb/src/kernel/blocks/dbtup/DbtupExecQuery.cpp 2007-05-09 10:19:39 +08:00
+++ 1.48/storage/ndb/src/kernel/blocks/dbtup/DbtupExecQuery.cpp 2007-05-09 10:19:39 +08:00
@@ -1046,6 +1046,25 @@ int Dbtup::handleUpdateReq(Signal* signa
req_struct->attrinfo_len);
if (unlikely(retValue == -1))
goto error;
+ /**
+ * We compare the endian of the API node and own node here.
+ * If it is needed to convert endian, send the interpreted ATTRINFO
+ * back to DBLQH to log into REDO logs.
+ * Otherwise, it will log the received ATTRINFO from DBTC/DBLQH into
+ * REDO logs directly in DBLQH block.
+ * The byte order of ATTRINFO has been swapped in updateAttributes()
+ * function.
+ */
+ const Uint32 apiBlockRef = req_struct->rec_blockref;
+ bool needConvertEndian = compareEndianWithOwn(apiBlockRef);
+
+ if (needConvertEndian) {
+ Uint32 RlogSize= req_struct->attrinfo_len;
+ MEMCOPY_NO_WORDS(&clogMemBuffer[0],
+ &cinBuffer[0],
+ RlogSize);
+ sendLogAttrinfo(signal, RlogSize, operPtrP);
+ }
} else {
jam();
if (unlikely(interpreterStartLab(signal, req_struct) == -1))
@@ -1180,6 +1199,10 @@ int Dbtup::handleInsertReq(Signal* signa
Uint64 cmp[2];
};
+ // compare the endian of API node and own node to judge whether need handle endan.
+ const Uint32 apiBlockRef = req_struct->rec_blockref;
+ bool needConvertEndian = compareEndianWithOwn(apiBlockRef);
+
if (ERROR_INSERTED(4014))
{
dst = 0;
@@ -1247,6 +1270,22 @@ int Dbtup::handleInsertReq(Signal* signa
goto update_error;
}
+ /**
+ * If it is needed to convert endian, send the interpreted ATTRINFO
+ * back to DBLQH to log into REDO logs.
+ * Otherwise, it will log the received ATTRINFO from DBTC/DBLQH into
+ * REDO logs directly in DBLQH block.
+ * The byte order of ATTRINFO has been swapped in updateAttributes()
+ * function.
+ */
+ if (needConvertEndian) {
+ Uint32 RlogSize= req_struct->attrinfo_len;
+ MEMCOPY_NO_WORDS(&clogMemBuffer[0],
+ &cinBuffer[0],
+ RlogSize);
+ sendLogAttrinfo(signal, RlogSize, regOperPtr.p);
+ }
+
if (ERROR_INSERTED(4017))
{
goto null_check_error;
@@ -1688,6 +1727,28 @@ int Dbtup::interpreterStartLab(Signal* s
return -1;
}
}
+
+ /**
+ * Compare the endian of API node and own node here.
+ * If it is needed to convert endian, the byte order of the ATTRINFO
+ * will be swapped in the update attributes function.
+ * So we store the original ATTRINFO and send it to DBLQH so that
+ * it can be sent to the next replica node.
+ * While for the REDO log, we will send the byte order swapped
+ * ATTRINFO to DBLQH to log into REDO logs.
+ * If it's no need to convert endian, we just send the ATTRINFO
+ * after update attributes function to DBLQH to log REDO logs and
+ * and send to next replica.
+ */
+ const Uint32 apiBlockRef = req_struct->rec_blockref;
+ bool needConvertEndian = compareEndianWithOwn(apiBlockRef);
+
+ if (needConvertEndian) {
+ MEMCOPY_NO_WORDS(&caiBuffer[RlogSize],
+ &cinBuffer[RinstructionCounter],
+ RfinalUpdateLen);
+ }
+
if (RfinalUpdateLen > 0) {
jam();
/* ---------------------------------------------------------------- */
@@ -1738,6 +1799,12 @@ int Dbtup::interpreterStartLab(Signal* s
sendReadAttrinfo(signal, req_struct, RattroutCounter, regOperPtr);
if (RlogSize > 0) {
sendLogAttrinfo(signal, RlogSize, regOperPtr);
+ if (needConvertEndian) {
+ /**
+ * Send the original ATTRINFO to DBLQH.
+ */
+ sendOrigAttrinfo(signal, RlogSize, regOperPtr);
+ }
}
return 0;
} else {
@@ -1774,6 +1841,33 @@ void Dbtup::sendLogAttrinfo(Signal* sign
EXECUTE_DIRECT(DBLQH, GSN_TUP_ATTRINFO, signal, 3 + TlogSize);
}
+/* ---------------------------------------------------------------- */
+/* WHEN EXECUTION IS INTERPRETED AND IT IS NEEDED TO CONVERT */
+/* ENDIAN, WE NEED TO SEND SOME ORIGINAL ATTRINFO(BYTE-ORDER */
+/* NOT SWAPPED) TO LQH FOR SENDING TO BACKUP AND STANDBY */
+/* NODES. */
+/* ---------------------------------------------------------------- */
+void Dbtup::sendOrigAttrinfo(Signal* signal,
+ Uint32 TlogSize,
+ Operationrec * const regOperPtr)
+
+{
+ Uint32 TbufferIndex= 0;
+ signal->theData[0]= regOperPtr->userpointer;
+ while (TlogSize > 22) {
+ MEMCOPY_NO_WORDS(&signal->theData[3],
+ &caiBuffer[TbufferIndex],
+ 22);
+ EXECUTE_DIRECT(DBLQH, GSN_TUP_ORIG_ATTRINFO, signal, 25);
+ TbufferIndex += 22;
+ TlogSize -= 22;
+ }
+ MEMCOPY_NO_WORDS(&signal->theData[3],
+ &caiBuffer[TbufferIndex],
+ TlogSize);
+ EXECUTE_DIRECT(DBLQH, GSN_TUP_ORIG_ATTRINFO, signal, 3 + TlogSize);
+}
+
inline
Uint32
brancher(Uint32 TheInstruction, Uint32 TprogramCounter)
@@ -1938,6 +2032,29 @@ int Dbtup::interpreterNextLab(Signal* si
ah.setNULL();
Tlen= 1;
}
+
+ /**
+ * Compare the endian of API node and own node here.
+ * If it is needed to convert endian, the byte order of the update
+ * data(i.e. the ATTRINFO) will be swapped in the update attributes
+ * function.
+ * So we store the original ATTRINFO and send it to DBLQH so that
+ * it can be sent to the next replica node.
+ * While for the REDO log, we will send the byte order swapped
+ * ATTRINFO to DBLQH to log into REDO logs.
+ * If it's no need to convert endian, we just send the ATTRINFO
+ * after update attributes function to DBLQH to log REDO logs and
+ * and send to next replica.
+ */
+ const Uint32 apiBlockRef = req_struct->rec_blockref;
+ bool needConvertEndian = compareEndianWithOwn(apiBlockRef);
+
+ if (needConvertEndian) {
+ caiBuffer[TdataWritten + 0]= TdataForUpdate[0];
+ caiBuffer[TdataWritten + 1]= TdataForUpdate[1];
+ caiBuffer[TdataWritten + 2]= TdataForUpdate[2];
+ }
+
int TnoDataRW= updateAttributes(req_struct,
&TdataForUpdate[0],
Tlen);
@@ -2926,6 +3043,8 @@ Dbtup::nr_read_pk(Uint32 fragPtrI,
return -1;
KeyReqStruct req_struct;
+ // initialize rec_blockref in case use it later
+ req_struct.rec_blockref = 0;
Uint32* ptr= ((Fix_page*)page_ptr.p)->get_ptr(key->m_page_idx, 0);
req_struct.m_page_ptr = page_ptr;
--- 1.32/storage/ndb/src/kernel/blocks/dbtup/DbtupGen.cpp 2007-05-09 10:19:39 +08:00
+++ 1.33/storage/ndb/src/kernel/blocks/dbtup/DbtupGen.cpp 2007-05-09 10:19:39 +08:00
@@ -112,6 +112,7 @@ Dbtup::Dbtup(Block_context& ctx, Pgman*
tableDescriptor = 0;
totNoOfPagesAllocated = 0;
cnoOfAllocatedPages = 0;
+ capiBlockref = 0;
initData();
}//Dbtup::Dbtup()
--- 1.20/storage/ndb/src/kernel/blocks/dbtup/DbtupIndex.cpp 2007-05-09 10:19:39 +08:00
+++ 1.21/storage/ndb/src/kernel/blocks/dbtup/DbtupIndex.cpp 2007-05-09 10:19:39 +08:00
@@ -144,6 +144,8 @@ Dbtup::tuxReadAttrs(Uint32 fragPtrI,
Operationrec tmpOp;
KeyReqStruct req_struct;
+ // initialize rec_blockref in case use it later
+ req_struct.rec_blockref= 0;
tmpOp.m_tuple_location.m_page_no= pageId;
tmpOp.m_tuple_location.m_page_idx= pageIndex;
@@ -217,6 +219,11 @@ Dbtup::tuxReadPk(Uint32 fragPtrI, Uint32
tmpOp.m_tuple_location.m_page_idx= pageIndex;
KeyReqStruct req_struct;
+ /**
+ * set req_struct.rec_blockref to capiBlockref,
+ * so that we can use it to judge the endian of API node while reading primary key.
+ */
+ req_struct.rec_blockref= capiBlockref;
PagePtr page_ptr;
Uint32* ptr= get_ptr(&page_ptr, &tmpOp.m_tuple_location, tablePtr.p);
@@ -343,6 +350,8 @@ Dbtup::tuxQueryTh(Uint32 fragPtrI,
// use temp op rec
Operationrec tempOp;
KeyReqStruct req_struct;
+ // initialize rec_blockref in case use it later
+ req_struct.rec_blockref= 0;
tempOp.m_tuple_location.m_page_no= getRealpid(fragPtr.p, fragPageId);
tempOp.m_tuple_location.m_page_idx= pageIndex;
tempOp.savepointId= savePointId;
--- 1.29/storage/ndb/src/kernel/blocks/dbtup/DbtupRoutines.cpp 2007-05-09 10:19:39 +08:00
+++ 1.30/storage/ndb/src/kernel/blocks/dbtup/DbtupRoutines.cpp 2007-05-09 10:19:39 +08:00
@@ -23,6 +23,7 @@
#include <AttributeDescriptor.hpp>
#include "AttributeOffset.hpp"
#include <AttributeHeader.hpp>
+#include <ndb_endian.h>
#define ljam() { jamLine(3000 + __LINE__); }
#define ljamEntry() { jamEntryLine(3000 + __LINE__); }
@@ -250,11 +251,17 @@ Dbtup::readFixedSizeTHOneWordNotNULL(Uin
Uint32 const wordRead= tuple_header[readOffset];
Uint32 newIndexBuf= indexBuf + 1;
Uint32 maxRead= req_struct->max_read;
+ // compare the endian of API node and own node.
+ const Uint32 apiBlockRef = req_struct->rec_blockref;
+ bool needConvertEndian = compareEndianWithOwn(apiBlockRef);
ndbrequire(readOffset < req_struct->check_offset[MM]);
if (newIndexBuf <= maxRead) {
ljam();
outBuffer[indexBuf]= wordRead;
+ if (needConvertEndian) {
+ swapFixedSizeAttr(&outBuffer[indexBuf], req_struct->attr_descriptor, 1);
+ }
ahOut->setDataSize(1);
req_struct->out_buf_index= newIndexBuf;
return true;
@@ -278,6 +285,9 @@ Dbtup::readFixedSizeTHTwoWordNotNULL(Uin
Uint32 const wordReadSecond= tuple_header[readOffset + 1];
Uint32 newIndexBuf= indexBuf + 2;
Uint32 maxRead= req_struct->max_read;
+ // compare the endian of API node and own node.
+ const Uint32 apiBlockRef = req_struct->rec_blockref;
+ bool needConvertEndian = compareEndianWithOwn(apiBlockRef);
ndbrequire(readOffset + 1 < req_struct->check_offset[MM]);
if (newIndexBuf <= maxRead) {
@@ -285,6 +295,9 @@ Dbtup::readFixedSizeTHTwoWordNotNULL(Uin
ahOut->setDataSize(2);
outBuffer[indexBuf]= wordReadFirst;
outBuffer[indexBuf + 1]= wordReadSecond;
+ if (needConvertEndian) {
+ swapFixedSizeAttr(&outBuffer[indexBuf], req_struct->attr_descriptor, 2);
+ }
req_struct->out_buf_index= newIndexBuf;
return true;
} else {
@@ -307,6 +320,9 @@ Dbtup::readFixedSizeTHManyWordNotNULL(Ui
Uint32 attrNoOfWords= AttributeDescriptor::getSizeInWords(attrDescriptor);
Uint32 maxRead= req_struct->max_read;
Uint32 charsetFlag = AttributeOffset::getCharsetFlag(attrDes2);
+ // compare the endian of API node and own node.
+ const Uint32 apiBlockRef = req_struct->rec_blockref;
+ bool needConvertEndian = compareEndianWithOwn(apiBlockRef);
ndbrequire((readOffset + attrNoOfWords - 1) < req_struct->check_offset[MM]);
if (! charsetFlag || ! req_struct->xfrm_flag) {
@@ -318,6 +334,10 @@ Dbtup::readFixedSizeTHManyWordNotNULL(Ui
&tuple_header[readOffset],
attrNoOfWords);
req_struct->out_buf_index = newIndexBuf;
+
+ if (needConvertEndian) {
+ swapFixedSizeAttr(&outBuffer[indexBuf], attrDescriptor, attrNoOfWords);
+ }
return true;
} else {
ljam();
@@ -353,6 +373,10 @@ Dbtup::readFixedSizeTHManyWordNotNULL(Ui
Uint32 newIndexBuf = indexBuf + (m >> 2);
ndbrequire(newIndexBuf <= maxRead);
req_struct->out_buf_index = newIndexBuf;
+
+ if (needConvertEndian) {
+ swapFixedSizeAttr(&outBuffer[indexBuf], attrDescriptor, (m >> 2));
+ }
return true;
} else {
ljam();
@@ -462,6 +486,9 @@ Dbtup::readVarSizeNotNULL(Uint32* out_bu
Uint32 attr_descriptor, index_buf, var_index;
Uint32 vsize_in_bytes, vsize_in_words, new_index, max_var_size;
Uint32 var_attr_pos, max_read;
+ // compare the endian of API node and own node.
+ const Uint32 apiBlockRef = req_struct->rec_blockref;
+ bool needConvertEndian = compareEndianWithOwn(apiBlockRef);
Uint32 idx= req_struct->m_var_data[MM].m_var_len_offset;
var_index= AttributeOffset::getOffset(attr_des2);
@@ -486,6 +513,14 @@ Dbtup::readVarSizeNotNULL(Uint32* out_bu
req_struct->m_var_data[MM].m_data_ptr+var_attr_pos,
vsize_in_bytes);
req_struct->out_buf_index= new_index;
+
+ if (needConvertEndian) {
+ /*
+ * swap the byte order for each byte of each 4-byte word.
+ */
+ ndbSwapManyWords32(out_buffer+index_buf, vsize_in_words);
+ }
+
return true;
}
}
@@ -522,6 +557,13 @@ Dbtup::readVarSizeNotNULL(Uint32* out_bu
Uint32 newIndexBuf = index_buf + (m >> 2);
ndbrequire(newIndexBuf <= max_read);
req_struct->out_buf_index = newIndexBuf;
+
+ if (needConvertEndian) {
+ /*
+ * swap the byte order for each byte of each 4-byte word.
+ */
+ ndbSwapManyWords32(out_buffer+index_buf, m >> 2);
+ }
return true;
}
}
@@ -584,6 +626,9 @@ Dbtup::readDiskFixedSizeNotNULL(Uint32*
Uint32 attrNoOfWords= AttributeDescriptor::getSizeInWords(attrDescriptor);
Uint32 maxRead= req_struct->max_read;
Uint32 charsetFlag = AttributeOffset::getCharsetFlag(attrDes2);
+ // compare the endian of API node and own node.
+ const Uint32 apiBlockRef = req_struct->rec_blockref;
+ bool needConvertEndian = compareEndianWithOwn(apiBlockRef);
ndbrequire((readOffset + attrNoOfWords - 1) < req_struct->check_offset[DD]);
if (! charsetFlag || ! req_struct->xfrm_flag) {
@@ -595,6 +640,11 @@ Dbtup::readDiskFixedSizeNotNULL(Uint32*
&tuple_header[readOffset],
attrNoOfWords);
req_struct->out_buf_index = newIndexBuf;
+
+ if (needConvertEndian) {
+ swapFixedSizeAttr(&outBuffer[indexBuf], attrDescriptor, attrNoOfWords);
+ }
+
return true;
} else {
ljam();
@@ -630,6 +680,11 @@ Dbtup::readDiskFixedSizeNotNULL(Uint32*
Uint32 newIndexBuf = indexBuf + (m >> 2);
ndbrequire(newIndexBuf <= maxRead);
req_struct->out_buf_index = newIndexBuf;
+
+ if (needConvertEndian) {
+ swapFixedSizeAttr(&outBuffer[indexBuf], attrDescriptor, (m >> 2));
+ }
+
return true;
} else {
ljam();
@@ -667,6 +722,9 @@ Dbtup::readDiskVarSizeNotNULL(Uint32* ou
Uint32 attr_descriptor, index_buf, var_index;
Uint32 vsize_in_bytes, vsize_in_words, new_index, max_var_size;
Uint32 var_attr_pos, max_read;
+ // compare the endian of API node and own node.
+ const Uint32 apiBlockRef = req_struct->rec_blockref;
+ bool needConvertEndian = compareEndianWithOwn(apiBlockRef);
Uint32 idx= req_struct->m_var_data[DD].m_var_len_offset;
var_index= AttributeOffset::getOffset(attr_des2);
@@ -687,6 +745,14 @@ Dbtup::readDiskVarSizeNotNULL(Uint32* ou
req_struct->m_var_data[DD].m_data_ptr+var_attr_pos,
vsize_in_bytes);
req_struct->out_buf_index= new_index;
+
+ if (needConvertEndian) {
+ /*
+ * swap the byte order for each byte of each 4-byte word.
+ */
+ ndbSwapManyWords32(out_buffer+index_buf, vsize_in_words);
+ }
+
return true;
} else {
ljam();
@@ -814,14 +880,48 @@ Dbtup::checkUpdateOfPrimaryKey(KeyReqStr
Uint32 xfrmBuffer[1 + MAX_KEY_SIZE_IN_WORDS * MAX_XFRM_MULTIPLY];
Uint32 charsetFlag = AttributeOffset::getCharsetFlag(attributeOffset);
if (charsetFlag) {
+ // compare the endian of API node and own node.
+ const Uint32 apiBlockRef = req_struct->rec_blockref;
+ bool needConvertEndian = compareEndianWithOwn(apiBlockRef);
+
+ Uint32 tmpKeyBuffer[1 + MAX_KEY_SIZE_IN_WORDS];
Uint32 csIndex = AttributeOffset::getCharsetPos(attributeOffset);
CHARSET_INFO* cs = regTabPtr->charsetArray[csIndex];
Uint32 srcPos = 0;
Uint32 dstPos = 0;
- xfrm_attr(attrDescriptor, cs, &updateBuffer[1], srcPos,
+
+ Uint32 attrWords = ahIn.getDataSize();
+ Uint32 attrBytes = attrWords << 2;
+ memcpy(tmpKeyBuffer, updateBuffer, 4 + attrBytes);
+
+ if (needConvertEndian) {
+ // should swap byte order of attribute before calling xfrm_attr().
+ bool ok = convert_endian_attr(attrDescriptor, cs, &tmpKeyBuffer[1], srcPos);
+ if (unlikely(!ok))
+ return true;
+ }
+
+ srcPos = 0;
+ dstPos = 0;
+
+ xfrm_attr(attrDescriptor, cs, &tmpKeyBuffer[1], srcPos,
&xfrmBuffer[1], dstPos, MAX_KEY_SIZE_IN_WORDS * MAX_XFRM_MULTIPLY);
ahIn.setDataSize(dstPos);
xfrmBuffer[0] = ahIn.m_value;
+
+ srcPos = 0;
+
+ if (needConvertEndian) {
+ /*
+ * Then should turn back byte order of attribute, so that can compare with
+ * the data read, because the data read also is swapped byte order while
+ * reading if the sender and receiver have different endian.
+ */
+ bool ok = convert_endian_xfrm_attr(attrDescriptor, cs, &xfrmBuffer[1], srcPos, ahIn.getDataSize());
+ if (unlikely(!ok))
+ return true;
+ }
+
updateBuffer = xfrmBuffer;
}
@@ -867,8 +967,15 @@ Dbtup::updateFixedSizeTHOneWordNotNULL(U
Uint32 newIndex= indexBuf + 2;
Uint32 *tuple_header= req_struct->m_tuple_ptr->m_data;
ndbrequire(updateOffset < req_struct->check_offset[MM]);
+ // compare the endian of API node and own node.
+ const Uint32 apiBlockRef = req_struct->rec_blockref;
+ bool needConvertEndian = compareEndianWithOwn(apiBlockRef);
if (newIndex <= inBufLen) {
+ if (needConvertEndian) {
+ swapFixedSizeAttr(&inBuffer[indexBuf + 1], req_struct->attr_descriptor, 1);
+ }
+
Uint32 updateWord= inBuffer[indexBuf + 1];
if (!nullIndicator) {
ljam();
@@ -901,8 +1008,15 @@ Dbtup::updateFixedSizeTHTwoWordNotNULL(U
Uint32 newIndex= indexBuf + 3;
Uint32 *tuple_header= req_struct->m_tuple_ptr->m_data;
ndbrequire((updateOffset + 1) < req_struct->check_offset[MM]);
+ // compare the endian of API node and own node.
+ const Uint32 apiBlockRef = req_struct->rec_blockref;
+ bool needConvertEndian = compareEndianWithOwn(apiBlockRef);
if (newIndex <= inBufLen) {
+ if (needConvertEndian) {
+ swapFixedSizeAttr(&inBuffer[indexBuf + 1], req_struct->attr_descriptor, 2);
+ }
+
Uint32 updateWord1= inBuffer[indexBuf + 1];
Uint32 updateWord2= inBuffer[indexBuf + 2];
if (!nullIndicator) {
@@ -933,6 +1047,9 @@ Dbtup::updateFixedSizeTHManyWordNotNULL(
Uint32 inBufLen= req_struct->in_buf_len;
Uint32 updateOffset= AttributeOffset::getOffset(attrDes2);
Uint32 charsetFlag = AttributeOffset::getCharsetFlag(attrDes2);
+ // compare the endian of API node and own node.
+ const Uint32 apiBlockRef = req_struct->rec_blockref;
+ bool needConvertEndian = compareEndianWithOwn(apiBlockRef);
AttributeHeader ahIn(inBuffer[indexBuf]);
Uint32 noOfWords= AttributeDescriptor::getSizeInWords(attrDescriptor);
@@ -944,6 +1061,10 @@ Dbtup::updateFixedSizeTHManyWordNotNULL(
if (newIndex <= inBufLen) {
if (!nullIndicator) {
ljam();
+ if (needConvertEndian) {
+ swapFixedSizeAttr(&inBuffer[indexBuf + 1], attrDescriptor, noOfWords);
+ }
+
if (charsetFlag) {
ljam();
Tablerec* regTabPtr = tabptr.p;
@@ -973,7 +1094,7 @@ Dbtup::updateFixedSizeTHManyWordNotNULL(
MEMCOPY_NO_WORDS(&tuple_header[updateOffset],
&inBuffer[indexBuf + 1],
noOfWords);
-
+
return true;
} else {
ljam();
@@ -1029,6 +1150,9 @@ Dbtup::updateVarSizeNotNULL(Uint32* in_b
Uint32 var_attr_pos;
char *var_data_start;
Uint16 *vpos_array;
+ // compare the endian of API node and own node.
+ const Uint32 apiBlockRef = req_struct->rec_blockref;
+ bool needConvertEndian = compareEndianWithOwn(apiBlockRef);
attr_descriptor= req_struct->attr_descriptor;
index_buf= req_struct->in_buf_index;
@@ -1052,9 +1176,17 @@ Dbtup::updateVarSizeNotNULL(Uint32* in_b
vpos_array[var_index+idx]= var_attr_pos+size_in_bytes;
req_struct->in_buf_index= new_index;
+ if (needConvertEndian) {
+ /*
+ * swap the byte order for each byte of each 4-byte word.
+ */
+ ndbSwapManyWords32(&in_buffer[index_buf + 1], vsize_in_words);
+ }
+
ndbrequire(var_attr_pos+size_in_bytes <= check_offset);
memcpy(var_data_start+var_attr_pos, &in_buffer[index_buf + 1],
size_in_bytes);
+
return true;
} else {
ljam();
@@ -1130,6 +1262,10 @@ Dbtup::read_pseudo(Uint32 attrId,
KeyReqStruct *req_struct,
Uint32* outBuffer)
{
+ // compare the endian of API node and own node.
+ const Uint32 apiBlockRef = req_struct->rec_blockref;
+ bool needConvertEndian = compareEndianWithOwn(apiBlockRef);
+
Uint32 tmp[sizeof(SignalHeader)+25];
Signal * signal = (Signal*)&tmp;
switch(attrId){
@@ -1141,6 +1277,9 @@ Dbtup::read_pseudo(Uint32 attrId,
Uint64 tmp= fragptr.p->noOfPages;
tmp*= 32768;
memcpy(outBuffer,&tmp,8);
+ if (needConvertEndian) {
+ ndbSwapManyWords64(outBuffer, 2);
+ }
}
return 2;
case AttributeHeader::FRAGMENT_VARSIZED_MEMORY:
@@ -1148,6 +1287,9 @@ Dbtup::read_pseudo(Uint32 attrId,
Uint64 tmp= fragptr.p->noOfVarPages;
tmp*= 32768;
memcpy(outBuffer,&tmp,8);
+ if (needConvertEndian) {
+ ndbSwapManyWords64(outBuffer, 2);
+ }
}
return 2;
case AttributeHeader::ROW_SIZE:
@@ -1161,6 +1303,9 @@ Dbtup::read_pseudo(Uint32 attrId,
EXECUTE_DIRECT(DBLQH, GSN_READ_PSEUDO_REQ, signal, 2);
outBuffer[0] = signal->theData[0];
outBuffer[1] = signal->theData[1];
+ if (needConvertEndian) {
+ ndbSwapManyWords64(outBuffer, 2);
+ }
return 2;
case AttributeHeader::RANGE_NO:
signal->theData[0] = operPtr.p->userpointer;
@@ -1171,6 +1316,10 @@ Dbtup::read_pseudo(Uint32 attrId,
return 1;
case AttributeHeader::DISK_REF:
{
+ /**
+ * FIXME: david.li
+ * Does here need convert endian ??
+ */
Uint32 *ref= req_struct->m_tuple_ptr->get_disk_ref_ptr(tabptr.p);
outBuffer[0] = ref[0];
outBuffer[1] = ref[1];
@@ -1187,6 +1336,10 @@ Dbtup::read_pseudo(Uint32 attrId,
outBuffer[3] = signal->theData[3];
return 4;
case AttributeHeader::ROWID:
+ /**
+ * FIXME: david.li
+ * Does here need convert endian ??
+ */
outBuffer[0] = req_struct->frag_page_id;
outBuffer[1] = operPtr.p->m_tuple_location.m_page_idx;
return 2;
@@ -1195,6 +1348,9 @@ Dbtup::read_pseudo(Uint32 attrId,
{
Uint64 tmp = * req_struct->m_tuple_ptr->get_mm_gci(tabptr.p);
memcpy(outBuffer, &tmp, sizeof(tmp));
+ if (needConvertEndian) {
+ ndbSwapManyWords64(outBuffer, 2);
+ }
return 2;
}
return 0;
@@ -1217,6 +1373,10 @@ Dbtup::readBitsNotNULL(Uint32* outBuffer
Uint32 newIndexBuf = indexBuf + ((bitCount + 31) >> 5);
Uint32 maxRead = req_struct->max_read;
Uint32 *bits= req_struct->m_tuple_ptr->get_null_bits(regTabPtr);
+ // compare the endian of API node and own node.
+ const Uint32 apiBlockRef = req_struct->rec_blockref;
+ bool needConvertEndian = compareEndianWithOwn(apiBlockRef);
+
if (newIndexBuf <= maxRead) {
ljam();
ahOut->setDataSize((bitCount + 31) >> 5);
@@ -1224,7 +1384,18 @@ Dbtup::readBitsNotNULL(Uint32* outBuffer
BitmaskImpl::getField(regTabPtr->m_offsets[MM].m_null_words, bits, pos,
bitCount, outBuffer+indexBuf);
-
+ Uint32 attrNoOfWords = (bitCount + 31) >> 5;
+
+ /**
+ * If the bit count is more than 32, the bits is stored in a Uint64 data,
+ * should swap it's byte order as Uint64.
+ * Else, the bits is stored in a Uint32 data, need not to swap byte order.
+ * The bit count is 64 at most.
+ */
+ if (needConvertEndian && attrNoOfWords == 2) {
+ ndbSwapManyWords64(&outBuffer[indexBuf], attrNoOfWords);
+ }
+
return true;
} else {
ljam();
@@ -1248,7 +1419,10 @@ Dbtup::readBitsNULLable(Uint32* outBuffe
Uint32 newIndexBuf = indexBuf + ((bitCount + 31) >> 5);
Uint32 maxRead = req_struct->max_read;
Uint32 *bits= req_struct->m_tuple_ptr->get_null_bits(regTabPtr);
-
+ // compare the endian of API node and own node.
+ const Uint32 apiBlockRef = req_struct->rec_blockref;
+ bool needConvertEndian = compareEndianWithOwn(apiBlockRef);
+
if(BitmaskImpl::get(regTabPtr->m_offsets[MM].m_null_words, bits, pos))
{
ljam();
@@ -1262,6 +1436,18 @@ Dbtup::readBitsNULLable(Uint32* outBuffe
req_struct->out_buf_index = newIndexBuf;
BitmaskImpl::getField(regTabPtr->m_offsets[MM].m_null_words, bits, pos+1,
bitCount, outBuffer+indexBuf);
+ Uint32 attrNoOfWords = (bitCount + 31) >> 5;
+
+ /**
+ * If the bit count is more than 32, the bits is stored in a Uint64 data,
+ * should swap it's byte order as Uint64.
+ * Else, the bits is stored in a Uint32 data, need not to swap byte order.
+ * The bit count is 64 at most.
+ */
+ if (needConvertEndian && attrNoOfWords == 2) {
+ ndbSwapManyWords64(&outBuffer[indexBuf], attrNoOfWords);
+ }
+
return true;
} else {
ljam();
@@ -1285,9 +1471,24 @@ Dbtup::updateBitsNotNULL(Uint32* inBuffe
AttributeDescriptor::getArraySize(req_struct->attr_descriptor);
Uint32 newIndex = indexBuf + 1 + ((bitCount + 31) >> 5);
Uint32 *bits= req_struct->m_tuple_ptr->get_null_bits(regTabPtr);
-
+ // compare the endian of API node and own node.
+ const Uint32 apiBlockRef = req_struct->rec_blockref;
+ bool needConvertEndian = compareEndianWithOwn(apiBlockRef);
+
if (newIndex <= inBufLen) {
if (!nullIndicator) {
+ Uint32 attrNoOfWords = (bitCount + 31) >> 5;
+
+ /**
+ * If the bit count is more than 32, the bits is stored in a Uint64 data,
+ * should swap it's byte order as Uint64.
+ * Else, the bits is stored in a Uint32 data, need not to swap byte order.
+ * The bit count is 64 at most.
+ */
+ if (needConvertEndian && attrNoOfWords == 2) {
+ ndbSwapManyWords64(inBuffer+indexBuf+1, attrNoOfWords);
+ }
+
BitmaskImpl::setField(regTabPtr->m_offsets[MM].m_null_words, bits, pos,
bitCount, inBuffer+indexBuf+1);
req_struct->in_buf_index = newIndex;
@@ -1318,9 +1519,24 @@ Dbtup::updateBitsNULLable(Uint32* inBuff
Uint32 bitCount =
AttributeDescriptor::getArraySize(req_struct->attr_descriptor);
Uint32 *bits= req_struct->m_tuple_ptr->get_null_bits(regTabPtr);
-
+ // compare the endian of API node and own node.
+ const Uint32 apiBlockRef = req_struct->rec_blockref;
+ bool needConvertEndian = compareEndianWithOwn(apiBlockRef);
+
if (!nullIndicator) {
BitmaskImpl::clear(regTabPtr->m_offsets[MM].m_null_words, bits, pos);
+ Uint32 attrNoOfWords = (bitCount + 31) >> 5;
+
+ /**
+ * If the bit count is more than 32, the bits is stored in a Uint64 data,
+ * should swap it's byte order as Uint64.
+ * Else, the bits is stored in a Uint32 data, need not to swap byte order.
+ * The bit count is 64 at most.
+ */
+ if (needConvertEndian && attrNoOfWords == 2) {
+ ndbSwapManyWords64(inBuffer+indexBuf+1, attrNoOfWords);
+ }
+
BitmaskImpl::setField(regTabPtr->m_offsets[MM].m_null_words, bits, pos+1,
bitCount, inBuffer+indexBuf+1);
@@ -1354,6 +1570,9 @@ Dbtup::updateDiskFixedSizeNotNULL(Uint32
Uint32 inBufLen= req_struct->in_buf_len;
Uint32 updateOffset= AttributeOffset::getOffset(attrDes2);
Uint32 charsetFlag = AttributeOffset::getCharsetFlag(attrDes2);
+ // compare the endian of API node and own node.
+ const Uint32 apiBlockRef = req_struct->rec_blockref;
+ bool needConvertEndian = compareEndianWithOwn(apiBlockRef);
AttributeHeader ahIn(inBuffer[indexBuf]);
Uint32 noOfWords= AttributeDescriptor::getSizeInWords(attrDescriptor);
@@ -1365,6 +1584,11 @@ Dbtup::updateDiskFixedSizeNotNULL(Uint32
if (newIndex <= inBufLen) {
if (!nullIndicator) {
ljam();
+
+ if (needConvertEndian) {
+ swapFixedSizeAttr(&inBuffer[indexBuf + 1], attrDescriptor, noOfWords);
+ }
+
if (charsetFlag) {
ljam();
Tablerec* regTabPtr = tabptr.p;
@@ -1449,6 +1673,9 @@ Dbtup::updateDiskVarSizeNotNULL(Uint32*
Uint32 var_attr_pos;
char *var_data_start;
Uint16 *vpos_array;
+ // compare the endian of API node and own node.
+ const Uint32 apiBlockRef = req_struct->rec_blockref;
+ bool needConvertEndian = compareEndianWithOwn(apiBlockRef);
attr_descriptor= req_struct->attr_descriptor;
index_buf= req_struct->in_buf_index;
@@ -1471,7 +1698,14 @@ Dbtup::updateDiskVarSizeNotNULL(Uint32*
var_data_start= req_struct->m_var_data[DD].m_data_ptr;
vpos_array[var_index+idx]= var_attr_pos+size_in_bytes;
req_struct->in_buf_index= new_index;
-
+
+ if (needConvertEndian) {
+ /*
+ * swap the byte order for each byte of each 4-byte word.
+ */
+ ndbSwapManyWords32(&in_buffer[index_buf + 1], vsize_in_words);
+ }
+
ndbrequire(var_attr_pos+size_in_bytes <= check_offset);
memcpy(var_data_start+var_attr_pos, &in_buffer[index_buf + 1],
size_in_bytes);
@@ -1539,6 +1773,10 @@ Dbtup::readDiskBitsNotNULL(Uint32* outBu
Uint32 newIndexBuf = indexBuf + ((bitCount + 31) >> 5);
Uint32 maxRead = req_struct->max_read;
Uint32 *bits= req_struct->m_disk_ptr->get_null_bits(regTabPtr, DD);
+ // compare the endian of API node and own node.
+ const Uint32 apiBlockRef = req_struct->rec_blockref;
+ bool needConvertEndian = compareEndianWithOwn(apiBlockRef);
+
if (newIndexBuf <= maxRead) {
ljam();
ahOut->setDataSize((bitCount + 31) >> 5);
@@ -1546,6 +1784,17 @@ Dbtup::readDiskBitsNotNULL(Uint32* outBu
BitmaskImpl::getField(regTabPtr->m_offsets[DD].m_null_words, bits, pos,
bitCount, outBuffer+indexBuf);
+ Uint32 attrNoOfWords = (bitCount + 31) >> 5;
+
+ /**
+ * If the bit count is more than 32, the bits is stored in a Uint64 data,
+ * should swap it's byte order as Uint64.
+ * Else, the bits is stored in a Uint32 data, need not to swap byte order.
+ * The bit count is 64 at most.
+ */
+ if (needConvertEndian && attrNoOfWords == 2) {
+ ndbSwapManyWords64(&outBuffer[indexBuf], attrNoOfWords);
+ }
return true;
} else {
@@ -1570,7 +1819,10 @@ Dbtup::readDiskBitsNULLable(Uint32* outB
Uint32 newIndexBuf = indexBuf + ((bitCount + 31) >> 5);
Uint32 maxRead = req_struct->max_read;
Uint32 *bits= req_struct->m_disk_ptr->get_null_bits(regTabPtr, DD);
-
+ // compare the endian of API node and own node.
+ const Uint32 apiBlockRef = req_struct->rec_blockref;
+ bool needConvertEndian = compareEndianWithOwn(apiBlockRef);
+
if(BitmaskImpl::get(regTabPtr->m_offsets[DD].m_null_words, bits, pos))
{
ljam();
@@ -1584,6 +1836,18 @@ Dbtup::readDiskBitsNULLable(Uint32* outB
req_struct->out_buf_index = newIndexBuf;
BitmaskImpl::getField(regTabPtr->m_offsets[DD].m_null_words, bits, pos+1,
bitCount, outBuffer+indexBuf);
+ Uint32 attrNoOfWords = (bitCount + 31) >> 5;
+
+ /**
+ * If the bit count is more than 32, the bits is stored in a Uint64 data,
+ * should swap it's byte order as Uint64.
+ * Else, the bits is stored in a Uint32 data, need not to swap byte order.
+ * The bit count is 64 at most.
+ */
+ if (needConvertEndian && attrNoOfWords == 2) {
+ ndbSwapManyWords64(&outBuffer[indexBuf], attrNoOfWords);
+ }
+
return true;
} else {
ljam();
@@ -1607,9 +1871,24 @@ Dbtup::updateDiskBitsNotNULL(Uint32* inB
AttributeDescriptor::getArraySize(req_struct->attr_descriptor);
Uint32 newIndex = indexBuf + 1 + ((bitCount + 31) >> 5);
Uint32 *bits= req_struct->m_disk_ptr->get_null_bits(regTabPtr, DD);
-
+ // compare the endian of API node and own node.
+ const Uint32 apiBlockRef = req_struct->rec_blockref;
+ bool needConvertEndian = compareEndianWithOwn(apiBlockRef);
+
if (newIndex <= inBufLen) {
if (!nullIndicator) {
+ Uint32 attrNoOfWords = (bitCount + 31) >> 5;
+
+ /**
+ * If the bit count is more than 32, the bits is stored in a Uint64 data,
+ * should swap it's byte order as Uint64.
+ * Else, the bits is stored in a Uint32 data, need not to swap byte order.
+ * The bit count is 64 at most.
+ */
+ if (needConvertEndian && attrNoOfWords == 2) {
+ ndbSwapManyWords64(inBuffer+indexBuf+1, attrNoOfWords);
+ }
+
BitmaskImpl::setField(regTabPtr->m_offsets[DD].m_null_words, bits, pos,
bitCount, inBuffer+indexBuf+1);
req_struct->in_buf_index = newIndex;
@@ -1640,9 +1919,24 @@ Dbtup::updateDiskBitsNULLable(Uint32* in
Uint32 bitCount =
AttributeDescriptor::getArraySize(req_struct->attr_descriptor);
Uint32 *bits= req_struct->m_disk_ptr->get_null_bits(regTabPtr, DD);
-
+ // compare the endian of API node and own node.
+ const Uint32 apiBlockRef = req_struct->rec_blockref;
+ bool needConvertEndian = compareEndianWithOwn(apiBlockRef);
+
if (!nullIndicator) {
BitmaskImpl::clear(regTabPtr->m_offsets[DD].m_null_words, bits, pos);
+ Uint32 attrNoOfWords = (bitCount + 31) >> 5;
+
+ /**
+ * If the bit count is more than 32, the bits is stored in a Uint64 data,
+ * should swap it's byte order as Uint64.
+ * Else, the bits is stored in a Uint32 data, need not to swap byte order.
+ * The bit count is 64 at most.
+ */
+ if (needConvertEndian && attrNoOfWords == 2) {
+ ndbSwapManyWords64(inBuffer+indexBuf+1, attrNoOfWords);
+ }
+
BitmaskImpl::setField(regTabPtr->m_offsets[DD].m_null_words, bits, pos+1,
bitCount, inBuffer+indexBuf+1);
@@ -1666,3 +1960,127 @@ Dbtup::updateDiskBitsNULLable(Uint32* in
}//if
}
+void
+Dbtup::swapFixedSizeAttr(Uint32* attrBuffer,
+ Uint32 attrDescriptor,
+ Uint32 attrNoOfWords)
+{
+ Uint32 typeId = AttributeDescriptor::getType(attrDescriptor);
+ Uint32 attrNoOfWords64 = (attrNoOfWords + 1) / 2;
+
+#if 0
+ // For test
+ Uint32 bytes = AttributeDescriptor::getSizeInBytes(attrDescriptor);
+ ndbout_c("test: attr bytes: %u, attr words: %u, attr words64: %u",
+ bytes, attrNoOfWords, attrNoOfWords64);
+ for (Uint32 i = 0; i < attrNoOfWords<<2; i++) {
+ ndbout_c("test: before swap attrBuffer[%u]: '%x'", i, ((unsigned char*)attrBuffer)[i]);
+ }
+#endif
+
+ switch (typeId) {
+ case NdbSqlUtil::Type::Tinyint:
+ case NdbSqlUtil::Type::Tinyunsigned:
+ /**
+ * 8 bits
+ * data is stored in the lowest 1 byte of a 4-byte word.
+ * should swap byte order for each byte of the word.
+ */
+ ndbSwapManyWords32(attrBuffer, attrNoOfWords);
+ break;
+ case NdbSqlUtil::Type::Smallint:
+ case NdbSqlUtil::Type::Smallunsigned:
+ /**
+ * 16 bits
+ * data is stored as Uint16.
+ * should swap byte order as Uint16.
+ */
+ ndbSwapManyWords16(attrBuffer, attrNoOfWords);
+ break;
+ case NdbSqlUtil::Type::Mediumint:
+ case NdbSqlUtil::Type::Mediumunsigned:
+ /**
+ * 24 bits
+ * data is stored in the lowest 3 bytes of a 4-byte word.
+ * should swap byte order for each byte of the word.
+ */
+ ndbSwapManyWords32(attrBuffer, attrNoOfWords);
+ break;
+ case NdbSqlUtil::Type::Bigint:
+ case NdbSqlUtil::Type::Bigunsigned:
+ case NdbSqlUtil::Type::Double:
+ case NdbSqlUtil::Type::Datetime:
+ /**
+ * 64 bits
+ * data is stored as Uint64.
+ * should swap byte order as Uint64.
+ */
+ ndbSwapManyWords64(attrBuffer, attrNoOfWords64 << 1);
+ break;
+ case NdbSqlUtil::Type::Olddecimal:
+ case NdbSqlUtil::Type::Olddecimalunsigned:
+ case NdbSqlUtil::Type::Decimal :
+ case NdbSqlUtil::Type::Decimalunsigned :
+ case NdbSqlUtil::Type::Char:
+ case NdbSqlUtil::Type::Binary:
+ /**
+ * data is stored in the byte order of character string.
+ * should swap byte order for each byte.
+ */
+ ndbSwapManyWords32(attrBuffer, attrNoOfWords);
+ break;
+ case NdbSqlUtil::Type::Varchar:
+ case NdbSqlUtil::Type::Varbinary:
+ case NdbSqlUtil::Type::Longvarchar:
+ case NdbSqlUtil::Type::Longvarbinary:
+ /**
+ * For variable sized disk data, it will call the fixed size function.
+ * data is stored in the byte order of character string.
+ * should swap byte order for each byte.
+ */
+ ndbSwapManyWords32(attrBuffer, attrNoOfWords);
+ break;
+ case NdbSqlUtil::Type::Date:
+ case NdbSqlUtil::Type::Time:
+ /**
+ * 24 bits
+ * data is stored in the lowest 3 bytes of a 4-byte word.
+ * should swap byte order for each byte of the word.
+ */
+ ndbSwapManyWords32(attrBuffer, attrNoOfWords);
+ break;
+ case NdbSqlUtil::Type::Blob:
+ case NdbSqlUtil::Type::Text:
+ /**
+ * The first 8 bytes of the Blob/Text data is a Uint64 data,
+ * should swap the byte order of it as Uint64.
+ * The left data of Blob/Text is stored as character string,
+ * should swap the byte order for each byte of it.
+ */
+ ndbSwapManyWords64(attrBuffer, 2);
+ ndbSwapManyWords32(attrBuffer + 2, attrNoOfWords - 2);
+ break;
+ case NdbSqlUtil::Type::Year:
+ /**
+ * 8 bits
+ * data is stored in the lowest 1 byte of a 4-byte word.
+ * should swap byte order for each byte of the word.
+ */
+ ndbSwapManyWords32(attrBuffer, attrNoOfWords);
+ break;
+ default:
+ /**
+ * the types that no need to handle endian:
+ * Int, Unsigned, Float, Timestamp.
+ * Bit will be handled specially in its handler function.
+ */
+ break;
+ }
+
+#if 0
+ // For test
+ for (Uint32 i = 0; i < attrNoOfWords<<2; i++) {
+ ndbout_c("test: after swap attrBuffer[%u]: '%x'", i, ((unsigned char*)attrBuffer)[i]);
+ }
+#endif
+}
--- 1.25/storage/ndb/src/kernel/blocks/dbtup/DbtupTrigger.cpp 2007-05-09 10:19:39 +08:00
+++ 1.26/storage/ndb/src/kernel/blocks/dbtup/DbtupTrigger.cpp 2007-05-09 10:19:39 +08:00
@@ -639,6 +639,7 @@ void Dbtup::executeTrigger(KeyReqStruct
TupTriggerData* const trigPtr,
Operationrec* const regOperPtr)
{
+
/**
* The block below does not work together with GREP.
* I have 2 db nodes (2 replicas) -> one node group.
@@ -695,6 +696,15 @@ void Dbtup::executeTrigger(KeyReqStruct
return;
}
}
+ /**
+ * If the attr info receiver is TC block, should change
+ * req_struct->rec_blockref to TC_ref to let readAttributes()
+ * to convert endian correctly.
+ */
+ if (trigPtr->triggerType == TriggerType::SECONDARY_INDEX) {
+ ljam();
+ req_struct->rec_blockref = req_struct->TC_ref;
+ }
if (!readTriggerInfo(trigPtr,
regOperPtr,
req_struct,
@@ -809,6 +819,7 @@ bool Dbtup::readTriggerInfo(TupTriggerDa
Uint32* const beforeBuffer,
Uint32& noBeforeWords)
{
+
//XXX this will not work with varsize attributes...
noAfterWords = 0;
noBeforeWords = 0;
--- 1.33/storage/ndb/src/kernel/blocks/dbtux/DbtuxScan.cpp 2007-05-09 10:19:39 +08:00
+++ 1.34/storage/ndb/src/kernel/blocks/dbtux/DbtuxScan.cpp 2007-05-09 10:19:39 +08:00
@@ -127,6 +127,14 @@ Dbtux::execTUX_BOUND_INFO(Signal* signal
ScanOp& scan = *c_scanOpPool.getPtr(req->tuxScanPtrI);
const Index& index = *c_indexPool.getPtr(scan.m_indexId);
const DescEnt& descEnt = getDescEnt(index.m_descPage, index.m_descOff);
+
+ /**
+ * We should compare the endian of the API node and own node here,
+ * if they are different, should handle the endian for the bound info.
+ */
+ const Uint32 apiBlockRef = req->scanApiBlockref;
+ bool needConvertEndian = compareEndianWithOwn(apiBlockRef);
+
// collect normalized lower and upper bounds
struct BoundInfo {
int type2; // with EQ -> LE/GE
@@ -165,6 +173,22 @@ Dbtux::execTUX_BOUND_INFO(Signal* signal
const DescAttr& descAttr = descEnt.m_descAttr[attrId];
Uint32 typeId = descAttr.m_typeId;
Uint32 maxBytes = AttributeDescriptor::getSizeInBytes(descAttr.m_attrDesc);
+ Uint32 srcPos = 0;
+ CHARSET_INFO* cs = NULL;
+ if (descAttr.m_charset != 0) {
+ cs = all_charsets[descAttr.m_charset];
+ }//if
+ if (needConvertEndian) {
+ // should swap byte order of attribute.
+ bool ok = convert_endian_attr(descAttr.m_attrDesc, cs, (Uint32*)srcPtr, srcPos);
+ if (unlikely(!ok)) {
+ jam();
+ scan.m_state = ScanOp::Invalid;
+ sig->errorCode = TuxBoundInfo::InvalidAttrInfo;
+ return;
+ }//if
+ }//if
+
Uint32 lb, len;
bool ok = NdbSqlUtil::get_var_length(typeId, srcPtr, maxBytes, lb, len);
if (! ok) {
@@ -187,7 +211,6 @@ Dbtux::execTUX_BOUND_INFO(Signal* signal
dstWords = srcWords;
} else {
jam();
- CHARSET_INFO* cs = all_charsets[descAttr.m_charset];
Uint32 xmul = cs->strxfrm_multiply;
if (xmul == 0)
xmul = 1;
--- 1.41/storage/ndb/src/kernel/blocks/qmgr/QmgrMain.cpp 2007-05-09 10:19:39 +08:00
+++ 1.42/storage/ndb/src/kernel/blocks/qmgr/QmgrMain.cpp 2007-05-09 10:19:39 +08:00
@@ -37,6 +37,7 @@
#include <signaldata/ApiBroadcast.hpp>
#include <ndb_version.h>
+#include <ndb_endian.h>
#ifdef DEBUG_ARBIT
#include <NdbOut.hpp>
@@ -989,6 +990,7 @@ Qmgr::sendCmNodeInfoReq(Signal* signal,
req->nodeId = getOwnNodeId();
req->dynamicId = self->ndynamicId;
req->version = getNodeInfo(getOwnNodeId()).m_version;
+ req->endian = getNodeInfo(getOwnNodeId()).m_endian;
const Uint32 ref = calcQmgrBlockRef(nodeId);
sendSignal(ref,GSN_CM_NODEINFOREQ, signal, CmNodeInfoReq::SignalLength, JBB);
DEBUG_START(GSN_CM_NODEINFOREQ, nodeId, "");
@@ -1503,6 +1505,7 @@ void Qmgr::execCM_NODEINFOCONF(Signal* s
replyNodePtr.p->ndynamicId = dynamicId;
replyNodePtr.p->blockRef = signal->getSendersBlockRef();
setNodeInfo(replyNodePtr.i).m_version = version;
+ setNodeInfo(replyNodePtr.i).m_endian = conf->endian;
if(!c_start.m_nodes.done()){
jam();
@@ -1554,6 +1557,7 @@ void Qmgr::execCM_NODEINFOREQ(Signal* si
addNodePtr.p->ndynamicId = req->dynamicId;
addNodePtr.p->blockRef = signal->getSendersBlockRef();
setNodeInfo(addNodePtr.i).m_version = req->version;
+ setNodeInfo(addNodePtr.i).m_endian = req->endian;
c_maxDynamicId = req->dynamicId;
cmAddPrepare(signal, addNodePtr, nodePtr.p);
@@ -1608,6 +1612,7 @@ Qmgr::cmAddPrepare(Signal* signal, NodeR
conf->nodeId = getOwnNodeId();
conf->dynamicId = self->ndynamicId;
conf->version = getNodeInfo(getOwnNodeId()).m_version;
+ conf->endian = getNodeInfo(getOwnNodeId()).m_endian;
sendSignal(nodePtr.p->blockRef, GSN_CM_NODEINFOCONF, signal,
CmNodeInfoConf::SignalLength, JBB);
DEBUG_START(GSN_CM_NODEINFOCONF, refToNode(nodePtr.p->blockRef), "");
@@ -2118,6 +2123,10 @@ void Qmgr::initData(Signal* signal)
execARBIT_CFG(signal);
}
setNodeInfo(getOwnNodeId()).m_version = NDB_VERSION;
+ /**
+ * Set the endian info of own node.
+ */
+ setNodeInfo(getOwnNodeId()).m_endian = ndbCheckEndian();
}//Qmgr::initData()
@@ -2665,6 +2674,7 @@ void Qmgr::execAPI_REGREQ(Signal* signal
ApiRegReq* req = (ApiRegReq*)signal->getDataPtr();
const Uint32 version = req->version;
+ const Uint32 endian = req->endian;
const BlockReference ref = req->ref;
NodeRecPtr apiNodePtr;
@@ -2707,6 +2717,10 @@ void Qmgr::execAPI_REGREQ(Signal* signal
}
setNodeInfo(apiNodePtr.i).m_version = version;
+ // store the endian of API node
+ if(getNodeInfo(apiNodePtr.i).m_endian != endian){
+ setNodeInfo(apiNodePtr.i).m_endian = endian;
+ }
setNodeInfo(apiNodePtr.i).m_heartbeat_cnt= 0;
@@ -2714,6 +2728,12 @@ void Qmgr::execAPI_REGREQ(Signal* signal
apiRegConf->qmgrRef = reference();
apiRegConf->apiHeartbeatFrequency = (chbApiDelay / 10);
apiRegConf->version = NDB_VERSION;
+ /**
+ * Because some API_REGREQ will come ealier than execution of Qmgr::initData(),
+ * here call ndbCheckEndian() instead of getNodeInfo().
+ */
+ //apiRegConf->endian = getNodeInfo(getOwnNodeId()).m_endian;
+ apiRegConf->endian = ndbCheckEndian();
NodeState state= apiRegConf->nodeState = getNodeState();
{
NodeRecPtr nodePtr;
@@ -2763,12 +2783,26 @@ Qmgr::execAPI_VERSION_REQ(Signal * signa
Uint32 senderRef = req->senderRef;
Uint32 nodeId = req->nodeId;
+ // judge whether need endian conversion
+ bool needConvertEndian = compareEndianWithOwn(senderRef);
+
ApiVersionConf * conf = (ApiVersionConf *)req;
if(getNodeInfo(nodeId).m_connected)
{
conf->version = getNodeInfo(nodeId).m_version;
struct in_addr in= globalTransporterRegistry.get_connect_address(nodeId);
conf->inet_addr= in.s_addr;
+ /**
+ * If the endian of the sender and receiver are different, the byte
+ * order of conf->inet_addr will be swapped, but conf->inet_addr
+ * already is network byte order before sending, so it is needed to
+ * turn back its byte order again.
+ * Swap the byte order before sending instead of turning it back on
+ * API node.
+ */
+ if (needConvertEndian) {
+ ndbSwapManyWords32(&(conf->inet_addr), sizeof(conf->inet_addr)>>2);
+ }
}
else
{
--- 1.3/storage/ndb/src/kernel/vm/SimplePropertiesSection.cpp 2007-05-09 10:19:39 +08:00
+++ 1.4/storage/ndb/src/kernel/vm/SimplePropertiesSection.cpp 2007-05-09 10:19:39 +08:00
@@ -17,9 +17,11 @@
#include <SimpleProperties.hpp>
#include <TransporterDefinitions.hpp>
#include "LongSignal.hpp"
+#include <ndb_endian.h>
+#include <signaldata/DictTabInfo.hpp>
SimplePropertiesSectionReader::SimplePropertiesSectionReader
-(struct SegmentedSectionPtr & ptr, class SectionSegmentPool & pool)
+(struct SegmentedSectionPtr & ptr, class SectionSegmentPool & pool, bool needConvertEndian)
: m_pool(pool)
{
if(ptr.p == 0){
@@ -27,11 +29,15 @@ SimplePropertiesSectionReader::SimplePro
m_len = 0;
m_head = 0;
m_currentSegment = 0;
+ m_convertEndian = needConvertEndian;
+ m_hasConvertedEndian = false;
} else {
m_pos = 0;
m_len = ptr.p->m_sz;
m_head = ptr.p;
m_currentSegment = ptr.p;
+ m_convertEndian = needConvertEndian;
+ m_hasConvertedEndian = false;
}
first();
}
@@ -82,6 +88,23 @@ bool
SimplePropertiesSectionReader::peekWord(Uint32 * dst) const {
if(m_pos < m_len){
Uint32 ind = m_pos % SectionSegment::DataLength;
+ /**
+ * If the endian of the sender and receiver are different,
+ * the byte order of the data will be swapped at the receiver end,
+ * so swap the byte order beforehand.
+ */
+ if (m_convertEndian && !m_hasConvertedEndian) {
+ ndbSwapManyWords32(&(m_currentSegment->theData[ind]), 1);
+ }
+
+#if 0
+ // For test
+ for (Uint32 i = 0; i < 4; i++) {
+ ndbout_c("test: dst[%u]: '%x'",
+ i, ((unsigned char*)&(m_currentSegment->theData[ind]))[i]);
+ }
+#endif
+
* dst = m_currentSegment->theData[ind];
return true;
}
@@ -97,7 +120,59 @@ SimplePropertiesSectionReader::peekWords
Uint32 left = (SectionSegment::DataLength - ind);
SectionSegment * p = m_currentSegment;
+ if (m_convertEndian && !m_hasConvertedEndian) {
+ /**
+ * It will call getValue() in the Constructor, and getValue() will
+ * handle endian conversion, and it maybe will call reset() then
+ * getWords() later, thus must consider it here, otherwise the first
+ * several words may be swapped 2 times.
+ */
+ if (m_pos == 0) {
+ SimpleProperties::SwapStatus swapStatus = getSwapStatus();
+ switch(swapStatus) {
+ case SimpleProperties::SwappedZeroWord:
+ // no need action
+ break;
+ case SimpleProperties::SwappedOneWord:
+ // turn it back
+ ndbSwapManyWords32(&(p->theData[ind]), 1);
+ break;
+ case SimpleProperties::SwappedTwoWords:
+ // turn it back
+ ndbSwapManyWords32(&(p->theData[ind]), 2);
+ break;
+ default:
+ break;
+ }//switch
+ }//if
+ }//if
+
while(len > left){
+ if (m_convertEndian && !m_hasConvertedEndian) {
+ Uint16 key = getKey();
+ switch (key) {
+ case DictTabInfo::ReplicaData:
+ case DictTabInfo::FragmentData:
+ // swap byte order for 16-bit words.
+ ndbSwapManyWords16(&(p->theData[ind]), left);
+ break;
+ default:
+ /**
+ * swap byte order for 32-bit words.
+ * Treat all the other Binary attributes as char string.
+ */
+ ndbSwapManyWords32(&(p->theData[ind]), left);
+ break;
+ }
+ }
+
+#if 0
+ // For test
+ for (Uint32 i = 0; i < left<<2; i++) {
+ ndbout_c("test: dst[%u]: '%x'", i, ((unsigned char*)&p->theData[ind])[i]);
+ }
+#endif
+
memcpy(dst, &p->theData[ind], 4 * left);
dst += left;
len -= left;
@@ -106,6 +181,31 @@ SimplePropertiesSectionReader::peekWords
p = m_pool.getPtr(p->m_nextSegment);
}
+ if (m_convertEndian && !m_hasConvertedEndian) {
+ Uint16 key = getKey();
+ switch (key) {
+ case DictTabInfo::ReplicaData:
+ case DictTabInfo::FragmentData:
+ // swap byte order for 16-bit words.
+ ndbSwapManyWords16(&(p->theData[ind]), len);
+ break;
+ default:
+ /**
+ * swap byte order for 32-bit words.
+ * Treat all the other Binary attributes as char string.
+ */
+ ndbSwapManyWords32(&(p->theData[ind]), len);
+ break;
+ }
+ }
+
+#if 0
+ // For test
+ for (Uint32 i = 0; i < len<<2; i++) {
+ ndbout_c("test: dst[%u]: '%x'", i, ((unsigned char*)&p->theData[ind])[i]);
+ }
+#endif
+
memcpy(dst, &p->theData[ind], 4 * len);
return true;
}
@@ -119,7 +219,18 @@ SimplePropertiesSectionReader::getWords(
return false;
}
-SimplePropertiesSectionWriter::SimplePropertiesSectionWriter(class SectionSegmentPool & pool)
+bool
+SimplePropertiesSectionReader::needConvertEndian() const {
+ return m_convertEndian;
+}
+
+void
+SimplePropertiesSectionReader::hasConvertedEndian(bool has_converted_endian) {
+ m_hasConvertedEndian = has_converted_endian;
+}
+
+SimplePropertiesSectionWriter::SimplePropertiesSectionWriter(class SectionSegmentPool & pool,
+ bool needConvertEndian)
: m_pool(pool)
{
Ptr<SectionSegment> first;
@@ -130,6 +241,7 @@ SimplePropertiesSectionWriter::SimplePro
m_head = 0;
m_currentSegment = 0;
m_prevPtrI = RNIL;
+ m_convertEndian = needConvertEndian;
return;
}
m_sz = 0;
@@ -138,6 +250,7 @@ SimplePropertiesSectionWriter::SimplePro
m_head->m_lastSegment = first.i;
m_currentSegment = first.p;
m_prevPtrI = RNIL;
+ m_convertEndian = needConvertEndian;
}
bool
@@ -220,4 +333,9 @@ SimplePropertiesSectionWriter::getPtr(st
m_pos = -1;
m_head = m_currentSegment = 0;
m_prevPtrI = RNIL;
+}
+
+bool
+SimplePropertiesSectionWriter::needConvertEndian() const {
+ return m_convertEndian;
}
--- 1.35/storage/ndb/src/kernel/vm/SimulatedBlock.cpp 2007-05-09 10:19:40 +08:00
+++ 1.36/storage/ndb/src/kernel/vm/SimulatedBlock.cpp 2007-05-09 10:19:40 +08:00
@@ -2053,5 +2053,444 @@ SimulatedBlock::create_distr_key(Uint32
return dstPos;
}
+/*
+ * Compare the endian of sender or receiver node with own node.
+ * If they are the same, return FALSE.
+ * Else, resturn TRUE.
+ */
+bool
+SimulatedBlock::compareEndianWithOwn(Uint32 otherBlockRef)
+{
+ const Uint32 otherNodeId = refToNode(otherBlockRef);
+ const Uint32 ownNodeId = getOwnNodeId();
+ Uint32 otherEndian;
+ Uint32 ownEndian;
+ if (otherNodeId != 0 && otherNodeId != ownNodeId) {
+ /**
+ * execute remotely
+ */
+ otherEndian = getNodeInfo(otherNodeId).m_endian;
+ ownEndian = getNodeInfo(ownNodeId).m_endian;
+ } else {
+ /**
+ * execute directly
+ */
+ otherEndian = ownEndian = getNodeInfo(ownNodeId).m_endian;
+ }
+
+ if (otherEndian != ownEndian)
+ {
+ return true;
+ }
+
+ return false;
+}
+
+bool
+SimulatedBlock::convert_endian_key(Uint32 tab, Uint32* src) const
+{
+ const KeyDescriptor * desc = g_key_descriptor_pool.getPtr(tab);
+ const Uint32 noOfKeyAttr = desc->noOfKeyAttr;
+
+ Uint32 i = 0;
+ Uint32 srcPos = 0;
+ while (i < noOfKeyAttr)
+ {
+ const KeyDescriptor::KeyAttr& keyAttr = desc->keyAttr[i];
+ bool ok =
+ convert_endian_attr(keyAttr.attributeDescriptor, keyAttr.charsetInfo,
+ src, srcPos);
+ if (unlikely(!ok))
+ return false;
+
+ i++;
+ }
+
+ return true;
+}
+
+bool
+SimulatedBlock::convert_endian_attr(Uint32 attrDesc, CHARSET_INFO* cs,
+ Uint32* src, Uint32& srcPos) const
+{
+ Uint32 attrBytes = AttributeDescriptor::getSizeInBytes(attrDesc);
+ Uint32 attrNoOfWords= AttributeDescriptor::getSizeInWords(attrDesc);
+ Uint32 attrNoOfWords64 = (attrNoOfWords + 1) / 2;
+ Uint32 typeId = AttributeDescriptor::getType(attrDesc);
+ Uint32 bitCount;
+ bool ok = false;
+
+#if 0
+ // For test
+ ndbout_c("test: attr type: %u", typeId);
+ ndbout_c("test: attr bytes: %u, attr words: %u, attr words64: %u",
+ attrBytes, attrNoOfWords, attrNoOfWords64);
+ for (Uint32 i = 0; i < attrBytes; i++) {
+ ndbout_c("test: before swap value[%u]: '%x'", i, ((char*)src + srcPos)[i]);
+ }
+#endif
+
+ switch (typeId) {
+ case NdbSqlUtil::Type::Tinyint:
+ case NdbSqlUtil::Type::Tinyunsigned:
+ /**
+ * 8 bits
+ * data is stored in the lowest 1 byte of a 4-byte word.
+ * should swap byte order for each byte of the word.
+ */
+ ndbSwapManyWords32((Uint32*)((char*)src + srcPos), attrNoOfWords);
+ break;
+ case NdbSqlUtil::Type::Smallint:
+ case NdbSqlUtil::Type::Smallunsigned:
+ /**
+ * 16 bits
+ * data is stored as Uint16.
+ * should swap byte order as Uint16.
+ */
+ ndbSwapManyWords16((Uint32*)((char*)src + srcPos), attrNoOfWords);
+ break;
+ case NdbSqlUtil::Type::Mediumint:
+ case NdbSqlUtil::Type::Mediumunsigned:
+ /**
+ * 24 bits
+ * data is stored in the lowest 3 bytes of a 4-byte word.
+ * should swap byte order for each byte of the word.
+ */
+ ndbSwapManyWords32((Uint32*)((char*)src + srcPos), attrNoOfWords);
+ break;
+ case NdbSqlUtil::Type::Bigint:
+ case NdbSqlUtil::Type::Bigunsigned:
+ case NdbSqlUtil::Type::Double:
+ case NdbSqlUtil::Type::Datetime:
+ /**
+ * 64 bits
+ * data is stored as Uint64.
+ * should swap byte order as Uint64.
+ */
+ ndbSwapManyWords64((Uint32*)((char*)src + srcPos), attrNoOfWords64 << 1);
+ // reset attrNoOfWords
+ attrNoOfWords = attrNoOfWords64 << 1;
+ break;
+ case NdbSqlUtil::Type::Olddecimal:
+ case NdbSqlUtil::Type::Olddecimalunsigned:
+ case NdbSqlUtil::Type::Decimal :
+ case NdbSqlUtil::Type::Decimalunsigned :
+ case NdbSqlUtil::Type::Char:
+ case NdbSqlUtil::Type::Binary:
+ /**
+ * data is stored in the byte order of character string.
+ * should swap byte order for each byte.
+ */
+ ndbSwapManyWords32((Uint32*)((char*)src + srcPos), attrNoOfWords);
+ break;
+ case NdbSqlUtil::Type::Varchar:
+ case NdbSqlUtil::Type::Varbinary:
+ case NdbSqlUtil::Type::Longvarchar:
+ case NdbSqlUtil::Type::Longvarbinary:
+ ok = convert_endian_var_attr(attrDesc, cs, src, srcPos, attrBytes);
+ if (unlikely(!ok))
+ return false;
+ // reset attrNoOfWords
+ attrNoOfWords = (attrBytes + 3) >> 2;
+ break;
+ case NdbSqlUtil::Type::Date:
+ case NdbSqlUtil::Type::Time:
+ /**
+ * 24 bits
+ * data is stored in the lowest 3 bytes of a 4-byte word.
+ * should swap byte order for each byte of the word.
+ */
+ ndbSwapManyWords32((Uint32*)((char*)src + srcPos), attrNoOfWords);
+ break;
+ case NdbSqlUtil::Type::Blob:
+ case NdbSqlUtil::Type::Text:
+ /**
+ * The first 8 bytes of the Blob/Text data is a Uint64 data,
+ * should swap the byte order of it as Uint64.
+ * The left data of Blob/Text is stored as character string,
+ * should swap the byte order for each byte of it.
+ */
+ ndbSwapManyWords64((Uint32*)((char*)src + srcPos), 2);
+ ndbSwapManyWords32((Uint32*)((char*)src + srcPos + 8), attrNoOfWords - 2);
+ break;
+ case NdbSqlUtil::Type::Bit:
+ bitCount = AttributeDescriptor::getArraySize(attrDesc);
+ attrNoOfWords = (bitCount + 31) >> 5;
+ /**
+ * If the bit count is more than 32, the bits is stored in a Uint64 data,
+ * should swap it's byte order as Uint64.
+ * Else, the bits is stored in a Uint32 data, need not to swap byte order.
+ * The bit count is 64 at most.
+ */
+ if (attrNoOfWords == 2) {
+ ndbSwapManyWords64((Uint32*)((char*)src + srcPos), attrNoOfWords);
+ }
+ break;
+ case NdbSqlUtil::Type::Year:
+ /**
+ * 8 bits
+ * data is stored in the lowest 1 byte of a 4-byte word.
+ * should swap byte order for each byte of the word.
+ */
+ ndbSwapManyWords32((Uint32*)((char*)src + srcPos), attrNoOfWords);
+ break;
+ default:
+ /**
+ * the types that no need to handle endian:
+ * Int, Unsigned, Float, Timestamp.
+ */
+ break;
+ }
+
+#if 0
+ // For test
+ for (Uint32 i = 0; i < attrBytes; i++) {
+ ndbout_c("test: after swap value[%u]: '%x'", i, ((char*)src + srcPos)[i]);
+ }
+#endif
+
+ // use attrNoOfWords to calculate the real attrBytes
+ attrBytes = attrNoOfWords << 2;
+ srcPos += attrBytes;
+
+ return true;
+}
+
+bool
+SimulatedBlock::convert_endian_var_attr(Uint32 attrDesc, CHARSET_INFO* cs,
+ Uint32* src, Uint32& srcPos, Uint32& attrBytes) const
+{
+ Uint32 typeId = AttributeDescriptor::getType(attrDesc);
+ Uint32 array = AttributeDescriptor::getArrayType(attrDesc);
+ Uint32 noOfWords;
+
+ /**
+ * The first 1 word(4 bytes) stores the length of the variable attribute,
+ * so swap the byte order of the first word firstly to get the length
+ * of the variable attribute.
+ */
+ Uint32 srcTmp;
+ memcpy(&srcTmp, ((char *)src + srcPos), 4);
+ ndbSwapManyWords32(&srcTmp, 1);
+
+ const uchar* srcPtr = (const uchar*)&srcTmp;
+ Uint32 varLen, varWords;
+
+ if (cs == NULL)
+ {
+ jam();
+ Uint32 len;
+ LINT_INIT(len);
+ switch(array){
+ case NDB_ARRAYTYPE_SHORT_VAR:
+ len = 1 + srcPtr[0];
+ break;
+ case NDB_ARRAYTYPE_MEDIUM_VAR:
+ len = 2 + srcPtr[0] + (srcPtr[1] << 8);
+ break;
+ default:
+ len = attrBytes;
+ break;
+ }
+ varLen = len;
+ varWords = (varLen + 3) >> 2;
+ }
+ else
+ {
+ jam();
+ Uint32 lb, len;
+ bool ok = NdbSqlUtil::get_var_length(typeId, srcPtr, attrBytes, lb, len);
+ if (unlikely(!ok))
+ return false;
+ varLen = lb + len;
+ varWords = (varLen + 3) >> 2;
+ }
+
+ attrBytes = varLen;
+ noOfWords = varWords;
+
+#if 0
+ // For test
+ ndbout_c("test: attrBytes: %u, noOfWords: %u", attrBytes, noOfWords);
+ for (Uint32 i = 0; i < attrBytes; i++) {
+ ndbout_c("test: before swap value[%u]: '%x'", i, ((char *)src + srcPos)[i]);
+ }
+#endif
+
+ // swap the var attribute
+ ndbSwapManyWords32((Uint32*)((char*)src + srcPos), noOfWords);
+
+#if 0
+ // For test
+ for (Uint32 i = 0; i < attrBytes; i++) {
+ ndbout_c("test: after swap value[%u]: '%x'", i, ((char *)src + srcPos)[i]);
+ }
+#endif
+
+ // the offset to the next key should be (noOfWords << 2)
+ attrBytes = noOfWords << 2;
+
+ return true;
+}
+
+/**
+ * This method is called to swap back the byte order of key attributes
+ * after called xfrm_key().
+ */
+bool
+SimulatedBlock::convert_endian_xfrm_key(Uint32 tab, Uint32* src,
+ Uint32 keyPartLen[MAX_ATTRIBUTES_IN_INDEX]) const
+{
+ const KeyDescriptor * desc = g_key_descriptor_pool.getPtr(tab);
+ const Uint32 noOfKeyAttr = desc->noOfKeyAttr;
+
+ Uint32 i = 0;
+ Uint32 srcPos = 0;
+ while (i < noOfKeyAttr)
+ {
+ const KeyDescriptor::KeyAttr& keyAttr = desc->keyAttr[i];
+ Uint32 keyLen = keyPartLen[i++];
+ bool ok =
+ convert_endian_xfrm_attr(keyAttr.attributeDescriptor, keyAttr.charsetInfo,
+ src, srcPos, keyLen);
+ if (unlikely(!ok))
+ return false;
+ }
+
+ return true;
+}
+
+bool
+SimulatedBlock::convert_endian_xfrm_attr(Uint32 attrDesc, CHARSET_INFO* cs,
+ Uint32* src, Uint32& srcPos, Uint32 keyLen) const
+{
+ Uint32 attrBytes = AttributeDescriptor::getSizeInBytes(attrDesc);
+ Uint32 attrNoOfWords= AttributeDescriptor::getSizeInWords(attrDesc);
+ Uint32 attrNoOfWords64 = (attrNoOfWords + 1) / 2;
+ Uint32 typeId = AttributeDescriptor::getType(attrDesc);
+ Uint32 bitCount;
+ bool ok = false;
+
+ switch (typeId) {
+ case NdbSqlUtil::Type::Tinyint:
+ case NdbSqlUtil::Type::Tinyunsigned:
+ /**
+ * 8 bits
+ * data is stored in the lowest 1 byte of a 4-byte word.
+ * should swap byte order for each byte of the word.
+ */
+ ndbSwapManyWords32((Uint32*)((char*)src + srcPos), attrNoOfWords);
+ break;
+ case NdbSqlUtil::Type::Smallint:
+ case NdbSqlUtil::Type::Smallunsigned:
+ /**
+ * 16 bits
+ * data is stored as Uint16.
+ * should swap byte order as Uint16.
+ */
+ ndbSwapManyWords16((Uint32*)((char*)src + srcPos), attrNoOfWords);
+ break;
+ case NdbSqlUtil::Type::Mediumint:
+ case NdbSqlUtil::Type::Mediumunsigned:
+ /**
+ * 24 bits
+ * data is stored in the lowest 3 bytes of a 4-byte word.
+ * should swap byte order for each byte of the word.
+ */
+ ndbSwapManyWords32((Uint32*)((char*)src + srcPos), attrNoOfWords);
+ break;
+ case NdbSqlUtil::Type::Bigint:
+ case NdbSqlUtil::Type::Bigunsigned:
+ case NdbSqlUtil::Type::Double:
+ case NdbSqlUtil::Type::Datetime:
+ /**
+ * 64 bits
+ * data is stored as Uint64.
+ * should swap byte order as Uint64.
+ */
+ ndbSwapManyWords64((Uint32*)((char*)src + srcPos), attrNoOfWords64 << 1);
+ // reset attrNoOfWords
+ attrNoOfWords = attrNoOfWords64 << 1;
+ break;
+ case NdbSqlUtil::Type::Olddecimal:
+ case NdbSqlUtil::Type::Olddecimalunsigned:
+ case NdbSqlUtil::Type::Decimal :
+ case NdbSqlUtil::Type::Decimalunsigned :
+ case NdbSqlUtil::Type::Char:
+ case NdbSqlUtil::Type::Binary:
+ /**
+ * data is stored in the byte order of character string.
+ * should swap byte order for each byte.
+ */
+ ndbSwapManyWords32((Uint32*)((char*)src + srcPos), attrNoOfWords);
+ break;
+ case NdbSqlUtil::Type::Varchar:
+ case NdbSqlUtil::Type::Varbinary:
+ case NdbSqlUtil::Type::Longvarchar:
+ case NdbSqlUtil::Type::Longvarbinary:
+ /**
+ * after xfrm_key(), var data is stored in the byte order of character string.
+ * should swap byte order for each byte.
+ */
+ ndbSwapManyWords32((Uint32*)((char*)src + srcPos), keyLen);
+ // reset attrNoOfWords
+ attrNoOfWords = keyLen;
+ break;
+ case NdbSqlUtil::Type::Date:
+ case NdbSqlUtil::Type::Time:
+ /**
+ * 24 bits
+ * data is stored in the lowest 3 bytes of a 4-byte word.
+ * should swap byte order for each byte of the word.
+ */
+ ndbSwapManyWords32((Uint32*)((char*)src + srcPos), attrNoOfWords);
+ break;
+ case NdbSqlUtil::Type::Blob:
+ case NdbSqlUtil::Type::Text:
+ /**
+ * The first 8 bytes of the Blob/Text data is a Uint64 data,
+ * should swap the byte order of it as Uint64.
+ * The left data of Blob/Text is stored as character string,
+ * should swap the byte order for each byte of it.
+ */
+ ndbSwapManyWords64((Uint32*)((char*)src + srcPos), 2);
+ ndbSwapManyWords32((Uint32*)((char*)src + srcPos + 8), attrNoOfWords - 2);
+ break;
+ case NdbSqlUtil::Type::Bit:
+ bitCount = AttributeDescriptor::getArraySize(attrDesc);
+ attrNoOfWords = (bitCount + 31) >> 5;
+ /**
+ * If the bit count is more than 32, the bits is stored in a Uint64 data,
+ * should swap it's byte order as Uint64.
+ * Else, the bits is stored in a Uint32 data, need not to swap byte order.
+ * The bit count is 64 at most.
+ */
+ if (attrNoOfWords == 2) {
+ ndbSwapManyWords64((Uint32*)((char*)src + srcPos), attrNoOfWords);
+ }
+ break;
+ case NdbSqlUtil::Type::Year:
+ /**
+ * 8 bits
+ * data is stored in the lowest 1 byte of a 4-byte word.
+ * should swap byte order for each byte of the word.
+ */
+ ndbSwapManyWords32((Uint32*)((char*)src + srcPos), attrNoOfWords);
+ break;
+ default:
+ /**
+ * the types that no need to handle endian:
+ * Int, Unsigned, Float, Timestamp.
+ */
+ break;
+ }
+
+ // use attrNoOfWords to calculate the real attrBytes
+ attrBytes = attrNoOfWords << 2;
+ srcPos += attrBytes;
+
+ return true;
+}
+
CArray<KeyDescriptor> g_key_descriptor_pool;
--- 1.26/storage/ndb/src/kernel/vm/SimulatedBlock.hpp 2007-05-09 10:19:40 +08:00
+++ 1.27/storage/ndb/src/kernel/vm/SimulatedBlock.hpp 2007-05-09 10:19:40 +08:00
@@ -424,6 +424,21 @@ protected:
Uint32 create_distr_key(Uint32 tableId,
Uint32 *data,
const Uint32 keyPaLen[MAX_ATTRIBUTES_IN_INDEX])const;
+
+ bool compareEndianWithOwn(Uint32 otherBlockRef);
+
+ /**
+ * convert endian for keyinfo
+ */
+ bool convert_endian_key(Uint32 tab, Uint32* src) const;
+ bool convert_endian_attr(Uint32 attrDesc, CHARSET_INFO* cs,
+ Uint32* src, Uint32& srcPos) const;
+ bool convert_endian_var_attr(Uint32 attrDesc, CHARSET_INFO* cs,
+ Uint32* src, Uint32& srcPos, Uint32& attrBytes) const;
+ bool convert_endian_xfrm_key(Uint32 tab, Uint32* src,
+ Uint32 keyPartLen[MAX_ATTRIBUTES_IN_INDEX]) const;
+ bool convert_endian_xfrm_attr(Uint32 attrDesc, CHARSET_INFO* cs,
+ Uint32* src, Uint32& srcPos, Uint32 keyLen) const;
private:
NewVARIABLE* NewVarRef; /* New Base Address Table for block */
@@ -717,11 +732,16 @@ SimulatedBlock::EXECUTE_DIRECT(Uint32 bl
Signal* signal,
Uint32 len){
signal->setLength(len);
+ /**
+ * For: WL#3615, Endian Task.
+ * Set the sender blockref here, so that can judge the endian
+ * of the sender node while executing signal.
+ */
+ signal->header.theSendersBlockRef = reference();
#ifdef VM_TRACE
if(globalData.testOn){
signal->header.theVerId_signalNumber = gsn;
signal->header.theReceiversBlockNumber = block;
- signal->header.theSendersBlockRef = reference();
globalSignalLoggers.executeDirect(signal->header,
0, // in
&signal->theData[0],
@@ -752,7 +772,6 @@ SimulatedBlock::EXECUTE_DIRECT(Uint32 bl
if(globalData.testOn){
signal->header.theVerId_signalNumber = gsn;
signal->header.theReceiversBlockNumber = block;
- signal->header.theSendersBlockRef = reference();
globalSignalLoggers.executeDirect(signal->header,
1, // out
&signal->theData[0],
--- 1.80/storage/ndb/src/mgmsrv/Services.cpp 2007-05-09 10:19:40 +08:00
+++ 1.81/storage/ndb/src/mgmsrv/Services.cpp 2007-05-09 10:19:40 +08:00
@@ -470,7 +470,6 @@ MgmApiSession::get_nodeid(Parser_t::Cont
const char * name= NULL;
Uint32 log_event= 1;
bool log_event_version;
- union { long l; char c[sizeof(long)]; } endian_check;
args.get("version", &version);
args.get("nodetype", &nodetype);
@@ -484,15 +483,6 @@ MgmApiSession::get_nodeid(Parser_t::Cont
args.get("timeout", &timeout);
/* for backwards compatability keep track if client uses new protocol */
log_event_version= args.get("log_event", &log_event);
-
- endian_check.l = 1;
- if(endian
- && strcmp(endian,(endian_check.c[sizeof(long)-1])?"big":"little")!=0) {
- m_output->println(cmd);
- m_output->println("result: Node does not have the same endianness as the management server.");
- m_output->println("");
- return;
- }
bool compatible;
switch (nodetype) {
--- 1.32/storage/ndb/src/ndbapi/ClusterMgr.cpp 2007-05-09 10:19:40 +08:00
+++ 1.33/storage/ndb/src/ndbapi/ClusterMgr.cpp 2007-05-09 10:19:40 +08:00
@@ -18,6 +18,7 @@
#include <my_pthread.h>
#include <ndb_limits.h>
#include <ndb_version.h>
+#include <ndb_endian.h>
#include "TransporterFacade.hpp"
#include "ClusterMgr.hpp"
@@ -192,6 +193,12 @@ ClusterMgr::forceHB()
ApiRegReq * req = CAST_PTR(ApiRegReq, signal.getDataPtrSend());
req->ref = numberToRef(API_CLUSTERMGR, theFacade.ownId());
req->version = NDB_VERSION;
+ /**
+ * Set the endian info of own node
+ */
+ const NodeId ownNodeId = theFacade.ownId();
+ Node & ownNode = theNodes[ownNodeId];
+ req->endian = ownNode.m_info.m_endian;
int nodeId= 0;
for(int i=0;
@@ -225,6 +232,17 @@ ClusterMgr::threadMain( ){
req->ref = numberToRef(API_CLUSTERMGR, theFacade.ownId());
req->version = NDB_VERSION;
+ /**
+ * Set the endian info of own node
+ */
+ const NodeId ownNodeId = theFacade.ownId();
+ Node & ownNode = theNodes[ownNodeId];
+ ownNode.m_info.m_endian = ndbCheckEndian();
+#ifdef DEBUG_REG
+ ndbout_c("ClusterMgr: own node ID: %d, own endian: %d",
+ ownNodeId, ownNode.m_info.m_endian);
+#endif
+ req->endian = ownNode.m_info.m_endian;
Uint32 timeSlept = 100;
Uint64 now = NdbTick_CurrentMillisecond();
@@ -384,6 +402,10 @@ ClusterMgr::execAPI_REGCONF(const Uint32
else
node.compatible = ndbCompatible_api_ndb(NDB_VERSION,
node.m_info.m_version);
+ }
+ // store the endian of remote node
+ if(node.m_info.m_endian != apiRegConf->endian){
+ node.m_info.m_endian = apiRegConf->endian;
}
node.m_state = apiRegConf->nodeState;
--- 1.8/storage/ndb/config/type_util.mk.am 2007-05-09 10:19:40 +08:00
+++ 1.9/storage/ndb/config/type_util.mk.am 2007-05-09 10:19:40 +08:00
@@ -7,4 +7,5 @@ INCLUDES += -I$(srcdir) \
-I$(top_srcdir)/storage/ndb/include \
-I$(top_srcdir)/storage/ndb/include/util \
-I$(top_srcdir)/storage/ndb/include/portlib \
- -I$(top_srcdir)/storage/ndb/include/logger
+ -I$(top_srcdir)/storage/ndb/include/logger \
+ -I$(top_srcdir)/storage/ndb/include/kernel
--- 1.13/storage/ndb/src/common/util/Makefile.am 2007-05-09 10:19:40 +08:00
+++ 1.14/storage/ndb/src/common/util/Makefile.am 2007-05-09 10:19:40 +08:00
@@ -7,7 +7,7 @@ libgeneral_la_SOURCES = \
SocketServer.cpp SocketClient.cpp SocketAuthenticator.cpp\
OutputStream.cpp NdbOut.cpp BaseString.cpp \
NdbSqlUtil.cpp new.cpp \
- uucode.c random.c version.c \
+ uucode.c random.c version.c ndb_endian.c \
strdup.c \
ConfigValues.cpp ndb_init.c basestring_vsnprintf.c \
Bitmask.cpp
| Thread |
|---|
| • bk commit into 5.1 tree (dli:1.2343) | David Li | 9 May |