4542 magnus.blaudd@stripped 2012-05-07 [merge]
Merge 7.0 -> 7.1
modified:
storage/ndb/include/kernel/signaldata/ScanFrag.hpp
storage/ndb/include/util/SocketAuthenticator.hpp
storage/ndb/src/common/transporter/Transporter.cpp
storage/ndb/src/common/transporter/Transporter.hpp
storage/ndb/src/common/util/SocketAuthenticator.cpp
storage/ndb/src/kernel/blocks/dblqh/DblqhMain.cpp
storage/ndb/src/kernel/blocks/dbtc/DbtcMain.cpp
storage/ndb/test/include/HugoTransactions.hpp
storage/ndb/test/include/NdbTimer.hpp
storage/ndb/test/ndbapi/testUpgrade.cpp
storage/ndb/test/src/HugoTransactions.cpp
storage/ndb/test/tools/connect.cpp
4541 Craig L Russell 2012-05-06
Improve life cycle of IndexBound, NdbInterpretedCode, NdbScanFilter, and NdbScanOptions
create and delete these objects in DbImpl (associated with the Ndb object)
delete these objects after the transaction.execute call
clean up these objects if an exception is thrown before the execute call
at Db.close, verify that the count of created and deleted objects matches
if mismatch, log a warning
modified:
storage/ndb/clusterj/clusterj-core/src/main/java/com/mysql/clusterj/core/query/QueryDomainTypeImpl.java
storage/ndb/clusterj/clusterj-core/src/main/java/com/mysql/clusterj/core/store/Operation.java
storage/ndb/clusterj/clusterj-tie/src/main/java/com/mysql/clusterj/tie/DbImpl.java
storage/ndb/clusterj/clusterj-tie/src/main/java/com/mysql/clusterj/tie/NdbRecordDeleteOperationImpl.java
storage/ndb/clusterj/clusterj-tie/src/main/java/com/mysql/clusterj/tie/NdbRecordIndexScanOperationImpl.java
storage/ndb/clusterj/clusterj-tie/src/main/java/com/mysql/clusterj/tie/NdbRecordKeyOperationImpl.java
storage/ndb/clusterj/clusterj-tie/src/main/java/com/mysql/clusterj/tie/NdbRecordOperationImpl.java
storage/ndb/clusterj/clusterj-tie/src/main/java/com/mysql/clusterj/tie/NdbRecordScanOperationImpl.java
storage/ndb/clusterj/clusterj-tie/src/main/java/com/mysql/clusterj/tie/NdbRecordTableScanOperationImpl.java
storage/ndb/clusterj/clusterj-tie/src/main/java/com/mysql/clusterj/tie/NdbRecordUniqueKeyOperationImpl.java
storage/ndb/clusterj/clusterj-tie/src/main/java/com/mysql/clusterj/tie/OperationImpl.java
=== modified file 'storage/ndb/include/kernel/signaldata/ScanFrag.hpp'
--- a/storage/ndb/include/kernel/signaldata/ScanFrag.hpp 2011-11-09 13:10:53 +0000
+++ b/storage/ndb/include/kernel/signaldata/ScanFrag.hpp 2012-05-03 09:48:34 +0000
@@ -89,6 +89,7 @@ public:
static void setDescendingFlag(Uint32 & requestInfo, Uint32 descending);
static void setTupScanFlag(Uint32 & requestInfo, Uint32 tupScan);
static void setAttrLen(Uint32 & requestInfo, Uint32 attrLen);
+ static void clearAttrLen(Uint32 & requestInfo);
static void setScanPrio(Uint32& requestInfo, Uint32 prio);
static void setNoDiskFlag(Uint32& requestInfo, Uint32 val);
static void setLcpScanFlag(Uint32 & requestInfo, Uint32 val);
@@ -277,7 +278,7 @@ public:
* 1111111111222222222233
* 01234567890123456789012345678901
* rrcdlxhkrztppppaaaaaaaaaaaaaaaa Short variant ( < 6.4.0)
- * rrcdlxhkrztppppAs Long variant (6.4.0 +)
+ * rrcdlxhkrztppppCs Long variant (6.4.0 +)
*/
#define SF_LOCK_MODE_SHIFT (5)
#define SF_LOCK_MODE_MASK (1)
@@ -422,6 +423,13 @@ ScanFragReq::setAttrLen(UintR & requestI
}
inline
+void
+ScanFragReq::clearAttrLen(Uint32 & requestInfo)
+{
+ requestInfo &= ~((Uint32)SF_ATTR_LEN_MASK << SF_ATTR_LEN_SHIFT);
+}
+
+inline
Uint32
ScanFragReq::getNoDiskFlag(const Uint32 & requestInfo){
return (requestInfo >> SF_NO_DISK_SHIFT) & 1;
=== modified file 'storage/ndb/include/util/SocketAuthenticator.hpp'
--- a/storage/ndb/include/util/SocketAuthenticator.hpp 2011-06-30 15:59:25 +0000
+++ b/storage/ndb/include/util/SocketAuthenticator.hpp 2012-05-07 07:38:13 +0000
@@ -1,5 +1,5 @@
/*
- Copyright (c) 2004, 2010, Oracle and/or its affiliates. All rights reserved.
+ Copyright (c) 2004, 2012, Oracle and/or its affiliates. All rights reserved.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -18,6 +18,8 @@
#ifndef SOCKET_AUTHENTICATOR_HPP
#define SOCKET_AUTHENTICATOR_HPP
+#include <NdbTCP.h>
+
class SocketAuthenticator
{
public:
@@ -29,8 +31,8 @@ public:
class SocketAuthSimple : public SocketAuthenticator
{
- const char *m_passwd;
- const char *m_username;
+ char *m_passwd;
+ char *m_username;
public:
SocketAuthSimple(const char *username, const char *passwd);
virtual ~SocketAuthSimple();
=== modified file 'storage/ndb/src/common/transporter/Transporter.cpp'
--- a/storage/ndb/src/common/transporter/Transporter.cpp 2012-03-21 15:31:06 +0000
+++ b/storage/ndb/src/common/transporter/Transporter.cpp 2012-04-24 08:33:27 +0000
@@ -51,7 +51,6 @@ Transporter::Transporter(TransporterRegi
DBUG_ENTER("Transporter::Transporter");
if (rHostName && strlen(rHostName) > 0){
strncpy(remoteHostName, rHostName, sizeof(remoteHostName));
- Ndb_getInAddr(&remoteHostAddress, rHostName);
}
else
{
=== modified file 'storage/ndb/src/common/transporter/Transporter.hpp'
--- a/storage/ndb/src/common/transporter/Transporter.hpp 2011-12-09 19:12:56 +0000
+++ b/storage/ndb/src/common/transporter/Transporter.hpp 2012-04-24 08:33:27 +0000
@@ -1,5 +1,5 @@
/*
- Copyright (c) 2003, 2011, Oracle and/or its affiliates. All rights reserved.
+ Copyright (c) 2003, 2012, Oracle and/or its affiliates. All rights reserved.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -139,8 +139,6 @@ protected:
*/
char remoteHostName[256];
char localHostName[256];
- struct in_addr remoteHostAddress;
- struct in_addr localHostAddress;
int m_s_port;
@@ -149,8 +147,6 @@ protected:
const bool isServer;
- unsigned createIndex;
-
int byteOrder;
bool compressionUsed;
bool checksumUsed;
=== modified file 'storage/ndb/src/common/util/SocketAuthenticator.cpp'
--- a/storage/ndb/src/common/util/SocketAuthenticator.cpp 2011-06-30 15:59:25 +0000
+++ b/storage/ndb/src/common/util/SocketAuthenticator.cpp 2012-05-07 07:38:13 +0000
@@ -1,5 +1,5 @@
/*
- Copyright (c) 2004, 2010, Oracle and/or its affiliates. All rights reserved.
+ Copyright (c) 2004, 2012, Oracle and/or its affiliates. All rights reserved.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -15,15 +15,10 @@
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
-
#include <ndb_global.h>
-
-#include <SocketClient.hpp>
#include <SocketAuthenticator.hpp>
#include <InputStream.hpp>
#include <OutputStream.hpp>
-#include <NdbOut.hpp>
-
SocketAuthSimple::SocketAuthSimple(const char *username, const char *passwd) {
if (username)
m_username= strdup(username);
@@ -38,9 +33,9 @@ SocketAuthSimple::SocketAuthSimple(const
SocketAuthSimple::~SocketAuthSimple()
{
if (m_passwd)
- free((void*)m_passwd);
+ free(m_passwd);
if (m_username)
- free((void*)m_username);
+ free(m_username);
}
bool SocketAuthSimple::client_authenticate(NDB_SOCKET_TYPE sockfd)
@@ -48,11 +43,18 @@ bool SocketAuthSimple::client_authentica
SocketOutputStream s_output(sockfd);
SocketInputStream s_input(sockfd);
+ // Write username and password
s_output.println("%s", m_username ? m_username : "");
s_output.println("%s", m_passwd ? m_passwd : "");
char buf[16];
- if (s_input.gets(buf, 16) == 0) return false;
+
+ // Read authentication result
+ if (s_input.gets(buf, sizeof(buf)) == 0)
+ return false;
+ buf[sizeof(buf)-1]= 0;
+
+ // Verify authentication result
if (strncmp("ok", buf, 2) == 0)
return true;
@@ -61,25 +63,24 @@ bool SocketAuthSimple::client_authentica
bool SocketAuthSimple::server_authenticate(NDB_SOCKET_TYPE sockfd)
{
-
SocketOutputStream s_output(sockfd);
SocketInputStream s_input(sockfd);
char buf[256];
- if (s_input.gets(buf, 256) == 0) return false;
- buf[255]= 0;
- if (m_username)
- free((void*)m_username);
- m_username= strdup(buf);
-
- if (s_input.gets(buf, 256) == 0) return false;
- buf[255]= 0;
- if (m_passwd)
- free((void*)m_passwd);
- m_passwd= strdup(buf);
+ // Read username
+ if (s_input.gets(buf, sizeof(buf)) == 0)
+ return false;
+ buf[sizeof(buf)-1]= 0;
+
+ // Read password
+ if (s_input.gets(buf, sizeof(buf)) == 0)
+ return false;
+ buf[sizeof(buf)-1]= 0;
+ // Write authentication result
s_output.println("ok");
return true;
}
+
=== modified file 'storage/ndb/src/kernel/blocks/dblqh/DblqhMain.cpp'
--- a/storage/ndb/src/kernel/blocks/dblqh/DblqhMain.cpp 2012-04-24 15:13:35 +0000
+++ b/storage/ndb/src/kernel/blocks/dblqh/DblqhMain.cpp 2012-05-07 07:49:18 +0000
@@ -9777,6 +9777,10 @@ void Dblqh::execSCAN_NEXTREQ(Signal* sig
const Uint32 transid2 = nextReq->transId2;
const Uint32 senderData = nextReq->senderData;
Uint32 hashHi = signal->getSendersBlockRef();
+ // bug#13834481 hashHi!=0 caused timeout (tx not found)
+ const NodeInfo& senderInfo = getNodeInfo(refToNode(hashHi));
+ if (unlikely(senderInfo.m_version < NDBD_LONG_SCANFRAGREQ))
+ hashHi = 0;
if (findTransaction(transid1, transid2, senderData, hashHi) != ZOK){
jam();
@@ -10291,8 +10295,10 @@ void Dblqh::execSCAN_FRAGREQ(Signal* sig
Uint32 hashIndex;
TcConnectionrecPtr nextHashptr;
Uint32 senderHi = signal->getSendersBlockRef();
-
- const Uint32 reqinfo = scanFragReq->requestInfo;
+ // bug#13834481 hashHi!=0 caused timeout (tx not found)
+ const NodeInfo& senderInfo = getNodeInfo(refToNode(senderHi));
+ if (unlikely(senderInfo.m_version < NDBD_LONG_SCANFRAGREQ))
+ senderHi = 0;
/* Short SCANFRAGREQ has no sections, Long SCANFRAGREQ has 1 or 2
* Section 0 : Mandatory ATTRINFO section
@@ -10322,9 +10328,17 @@ void Dblqh::execSCAN_FRAGREQ(Signal* sig
else
{
/* Short request, get Attr + Key len from signal */
- aiLen= ScanFragReq::getAttrLen(reqinfo);
+ aiLen= ScanFragReq::getAttrLen(scanFragReq->requestInfo);
keyLen= (scanFragReq->fragmentNoKeyLen >> 16);
+ /*
+ * bug#13834481. Clear attribute length so that it is not
+ * re-interpreted as new 7.x bits. initScanrec() uses signal
+ * data so we must modify signal data.
+ */
+ ScanFragReq::clearAttrLen(scanFragReq->requestInfo);
}
+
+ const Uint32 reqinfo = scanFragReq->requestInfo;
const Uint32 fragId = (scanFragReq->fragmentNoKeyLen & 0xFFFF);
tabptr.i = scanFragReq->tableId;
=== modified file 'storage/ndb/src/kernel/blocks/dbtc/DbtcMain.cpp'
--- a/storage/ndb/src/kernel/blocks/dbtc/DbtcMain.cpp 2012-04-24 14:24:54 +0000
+++ b/storage/ndb/src/kernel/blocks/dbtc/DbtcMain.cpp 2012-05-07 07:49:18 +0000
@@ -12009,7 +12009,11 @@ void Dbtc::sendScanFragReq(Signal* signa
*/
Uint32 reqAttrLen = sections.m_ptr[0].sz;
ScanFragReq::setAttrLen(req->requestInfo, reqAttrLen);
- req->fragmentNoKeyLen |= reqKeyLen;
+ /*
+ * bug#13834481 missing shift, causing fragment not found
+ * (error 1231) on 6.3 node.
+ */
+ req->fragmentNoKeyLen |= (reqKeyLen << 16);
sendSignal(scanFragP->lqhBlockref, GSN_SCAN_FRAGREQ, signal,
ScanFragReq::SignalLength, JBB);
if(reqKeyLen > 0)
=== modified file 'storage/ndb/test/include/HugoTransactions.hpp'
--- a/storage/ndb/test/include/HugoTransactions.hpp 2011-06-30 15:59:25 +0000
+++ b/storage/ndb/test/include/HugoTransactions.hpp 2012-05-03 09:54:05 +0000
@@ -26,6 +26,8 @@ class NDBT_Stats;
class HugoTransactions : public HugoOperations {
public:
+ struct HugoBound { int attr; int type; const void* value; };
+
HugoTransactions(const NdbDictionary::Table&,
const NdbDictionary::Index* idx = 0);
~HugoTransactions();
@@ -61,7 +63,8 @@ public:
int abort = 0,
int parallelism = 0,
NdbOperation::LockMode = NdbOperation::LM_Read,
- int scan_flags = 0);
+ int scan_flags = 0,
+ int bound_cnt = 0, const HugoBound* bound_arr = 0);
int pkReadRecords(Ndb*,
int records,
=== modified file 'storage/ndb/test/include/NdbTimer.hpp'
--- a/storage/ndb/test/include/NdbTimer.hpp 2011-02-02 00:40:07 +0000
+++ b/storage/ndb/test/include/NdbTimer.hpp 2012-04-23 19:00:46 +0000
@@ -23,7 +23,7 @@
#include <NdbOut.hpp>
//
-// Class used for measuring time and priting the results
+// Class used for measuring time and printing the results
//
// Currently measures time in milliseconds
//
=== modified file 'storage/ndb/test/ndbapi/testUpgrade.cpp'
--- a/storage/ndb/test/ndbapi/testUpgrade.cpp 2011-06-30 15:59:25 +0000
+++ b/storage/ndb/test/ndbapi/testUpgrade.cpp 2012-05-03 09:54:05 +0000
@@ -592,9 +592,38 @@ int runCheckStarted(NDBT_Context* ctx, N
return NDBT_OK;
}
+int
+runCreateIndexT1(NDBT_Context* ctx, NDBT_Step* step)
+{
+ Ndb* pNdb = GETNDB(step);
+ NdbDictionary::Dictionary* pDict = pNdb->getDictionary();
+ const NdbDictionary::Table* pTab = pDict->getTable("T1");
+ if (pTab == 0)
+ {
+ g_err << "getTable(T1) error: " << pDict->getNdbError() << endl;
+ return NDBT_FAILED;
+ }
+ NdbDictionary::Index ind;
+ ind.setName("T1X1");
+ ind.setTable("T1");
+ ind.setType(NdbDictionary::Index::OrderedIndex);
+ ind.setLogging(false);
+ ind.addColumn("KOL2");
+ ind.addColumn("KOL3");
+ ind.addColumn("KOL4");
+ if (pDict->createIndex(ind, *pTab) != 0)
+ {
+ g_err << "createIndex(T1X1) error: " << pDict->getNdbError() << endl;
+ return NDBT_FAILED;
+ }
+ return NDBT_OK;
+}
+
int
runCreateAllTables(NDBT_Context* ctx, NDBT_Step* step)
{
+ Uint32 useRangeScanT1 = ctx->getProperty("UseRangeScanT1", (Uint32)0);
+
ndbout_c("createAllTables");
if (NDBT_Tables::createAllTables(GETNDB(step), false, true))
return NDBT_FAILED;
@@ -602,6 +631,10 @@ runCreateAllTables(NDBT_Context* ctx, ND
for (int i = 0; i<NDBT_Tables::getNumTables(); i++)
table_list.push_back(BaseString(NDBT_Tables::getTable(i)->getName()));
+ if (useRangeScanT1)
+ if (runCreateIndexT1(ctx, step) != NDBT_OK)
+ return NDBT_FAILED;
+
return NDBT_OK;
}
@@ -680,6 +713,8 @@ runClearAll(NDBT_Context* ctx, NDBT_Step
int
runBasic(NDBT_Context* ctx, NDBT_Step* step)
{
+ Uint32 useRangeScanT1 = ctx->getProperty("UseRangeScanT1", (uint32)0);
+
Ndb* pNdb = GETNDB(step);
NdbDictionary::Dictionary * pDict = pNdb->getDictionary();
int records = ctx->getNumRecords();
@@ -705,6 +740,32 @@ runBasic(NDBT_Context* ctx, NDBT_Step* s
// (or check if it does)
if (strcmp(tab->getName(), "T1") == 0)
trans.pkInterpretedUpdateRecords(pNdb, records);
+ if (strcmp(tab->getName(), "T1") == 0 &&
+ useRangeScanT1)
+ {
+ const NdbDictionary::Index* pInd = pDict->getIndex("T1X1", "T1");
+ if (pInd == 0)
+ {
+ g_err << "getIndex(T1X1) error: " << pDict->getNdbError() << endl;
+ return NDBT_FAILED;
+ }
+ // bug#13834481 - bound values do not matter
+ const Uint32 lo = 0x11110000;
+ const Uint32 hi = 0xaaaa0000;
+ HugoTransactions::HugoBound bound_arr[6];
+ int bound_cnt = 0;
+ for (int j = 0; j <= 1; j++) {
+ int n = rand() % 4;
+ for (int i = 0; i < n; i++) {
+ HugoTransactions::HugoBound& b = bound_arr[bound_cnt++];
+ b.attr = i;
+ b.type = (j == 0 ? 0 : 2); // LE/GE
+ b.value = (j == 0 ? &lo : &hi);
+ }
+ }
+ g_info << "range scan T1 with " << bound_cnt << " bounds" << endl;
+ trans.scanReadRecords(pNdb, pInd, records, 0, 0, NdbOperation::LM_Read, 0, bound_cnt, bound_arr);
+ }
trans.clearTable(pNdb, records/2);
trans.loadTable(pNdb, records/2);
break;
@@ -1063,6 +1124,7 @@ POSTUPGRADE("Upgrade_FS")
TESTCASE("Upgrade_Traffic",
"Test upgrade with traffic, all tables and restart --initial")
{
+ TC_PROPERTY("UseRangeScanT1", (Uint32)1);
INITIALIZER(runCheckStarted);
INITIALIZER(runCreateAllTables);
STEP(runUpgrade_Traffic);
@@ -1077,6 +1139,7 @@ POSTUPGRADE("Upgrade_Traffic")
TESTCASE("Upgrade_Traffic_FS",
"Test upgrade with traffic, all tables and restart using FS")
{
+ TC_PROPERTY("UseRangeScanT1", (Uint32)1);
TC_PROPERTY("KeepFS", 1);
INITIALIZER(runCheckStarted);
INITIALIZER(runCreateAllTables);
=== modified file 'storage/ndb/test/src/HugoTransactions.cpp'
--- a/storage/ndb/test/src/HugoTransactions.cpp 2011-11-28 13:54:18 +0000
+++ b/storage/ndb/test/src/HugoTransactions.cpp 2012-05-03 09:54:05 +0000
@@ -199,7 +199,8 @@ HugoTransactions::scanReadRecords(Ndb* p
int abortPercent,
int parallelism,
NdbOperation::LockMode lm,
- int scan_flags)
+ int scan_flags,
+ int bound_cnt, const HugoBound* bound_arr)
{
int retryAttempt = 0;
@@ -242,6 +243,14 @@ HugoTransactions::scanReadRecords(Ndb* p
closeTransaction(pNdb);
return NDBT_FAILED;
}
+
+ for (int i = 0; i < bound_cnt; i++) {
+ const HugoBound& b = bound_arr[i];
+ if (pOp->setBound(b.attr, b.type, b.value) != 0) {
+ ERR(pOp->getNdbError());
+ return NDBT_FAILED;
+ }
+ }
for(a = 0; a<tab.getNoOfColumns(); a++){
if((row.attributeStore(a) =
@@ -350,8 +359,10 @@ HugoTransactions::scanReadRecords(Ndb* p
closeTransaction(pNdb);
- g_info << rows << " rows have been read" << endl;
- if (records != 0 && rows != records){
+ g_info << rows << " rows have been read"
+ << ", number of index bounds " << bound_cnt << endl;
+ // TODO verify expected number of records with index bounds
+ if (records != 0 && rows != records && bound_cnt == 0){
g_err << "Check expected number of records failed" << endl
<< " expected=" << records <<", " << endl
<< " read=" << rows << endl;
=== modified file 'storage/ndb/test/tools/connect.cpp'
--- a/storage/ndb/test/tools/connect.cpp 2011-09-13 09:08:04 +0000
+++ b/storage/ndb/test/tools/connect.cpp 2012-04-23 08:11:54 +0000
@@ -1,5 +1,5 @@
/*
- Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved.
+ Copyright (c) 2007, 2012, Oracle and/or its affiliates. All rights reserved.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -27,20 +27,18 @@ static int opt_drop = 1;
static int opt_subloop = 5;
static int opt_wait_all = 0;
-typedef uchar* gptr;
-
static struct my_option my_long_options[] =
{
- NDB_STD_OPTS("ndb_desc"),
+ NDB_STD_OPTS("ndb_connect"),
{ "loop", 'l', "loops",
- (gptr*) &opt_loop, (gptr*) &opt_loop, 0,
+ (uchar**) &opt_loop, (uchar**) &opt_loop, 0,
GET_INT, REQUIRED_ARG, opt_loop, 0, 0, 0, 0, 0 },
{ "sleep", 's', "Sleep (ms) between connection attempt",
- (gptr*) &opt_sleep, (gptr*) &opt_sleep, 0,
+ (uchar**) &opt_sleep, (uchar**) &opt_sleep, 0,
GET_INT, REQUIRED_ARG, opt_sleep, 0, 0, 0, 0, 0 },
{ "drop", 'd',
"Drop event operations before disconnect (0 = no, 1 = yes, else rand",
- (gptr*) &opt_drop, (gptr*) &opt_drop, 0,
+ (uchar**) &opt_drop, (uchar**) &opt_drop, 0,
GET_INT, REQUIRED_ARG, opt_drop, 0, 0, 0, 0, 0 },
{ "subscribe-loop", NDB_OPT_NOSHORT,
"Loop in subscribe/unsubscribe",
@@ -60,7 +58,7 @@ int main(int argc, char** argv){
load_defaults("my",load_default_groups,&argc,&argv);
int ho_error;
#ifndef DBUG_OFF
- opt_debug= "d:t:O,/tmp/ndb_desc.trace";
+ opt_debug= "d:t:O,/tmp/ndb_connect.trace";
#endif
if ((ho_error=handle_options(&argc, &argv, my_long_options,
ndb_std_get_one_option)))
No bundle (reason: useless for push emails).
| Thread |
|---|
| • bzr push into mysql-5.1-telco-7.1 branch (magnus.blaudd:4541 to 4542) | magnus.blaudd | 8 May |