summaryrefslogtreecommitdiff
path: root/ndb
diff options
context:
space:
mode:
Diffstat (limited to 'ndb')
-rw-r--r--ndb/src/kernel/blocks/dbtup/DbtupRoutines.cpp17
-rw-r--r--ndb/src/kernel/vm/SimulatedBlock.cpp92
-rw-r--r--ndb/src/kernel/vm/SimulatedBlock.hpp6
-rw-r--r--ndb/src/ndbapi/NdbImpl.hpp10
-rw-r--r--ndb/src/ndbapi/NdbRecAttr.cpp4
-rw-r--r--ndb/tools/ndb_size.pl87
-rw-r--r--ndb/tools/ndb_size.tmpl46
7 files changed, 198 insertions, 64 deletions
diff --git a/ndb/src/kernel/blocks/dbtup/DbtupRoutines.cpp b/ndb/src/kernel/blocks/dbtup/DbtupRoutines.cpp
index acdad3f9f1a..8a55777ac05 100644
--- a/ndb/src/kernel/blocks/dbtup/DbtupRoutines.cpp
+++ b/ndb/src/kernel/blocks/dbtup/DbtupRoutines.cpp
@@ -684,6 +684,21 @@ Dbtup::checkUpdateOfPrimaryKey(Uint32* updateBuffer, Tablerec* const regTabPtr)
Uint32 attrDescriptorIndex = regTabPtr->tabDescriptor + (attributeId << ZAD_LOG_SIZE);
Uint32 attrDescriptor = tableDescriptor[attrDescriptorIndex].tabDescr;
Uint32 attributeOffset = tableDescriptor[attrDescriptorIndex + 1].tabDescr;
+
+ Uint32 xfrmBuffer[1 + MAX_KEY_SIZE_IN_WORDS * MAX_XFRM_MULTIPLY];
+ Uint32 charsetFlag = AttributeOffset::getCharsetFlag(attributeOffset);
+ if (charsetFlag) {
+ Uint32 csIndex = AttributeOffset::getCharsetPos(attributeOffset);
+ CHARSET_INFO* cs = regTabPtr->charsetArray[csIndex];
+ Uint32 srcPos = 0;
+ Uint32 dstPos = 0;
+ xfrm_attr(attrDescriptor, cs, &updateBuffer[1], srcPos,
+ &xfrmBuffer[1], dstPos, MAX_KEY_SIZE_IN_WORDS * MAX_XFRM_MULTIPLY);
+ ahIn.setDataSize(dstPos);
+ xfrmBuffer[0] = ahIn.m_value;
+ updateBuffer = xfrmBuffer;
+ }
+
ReadFunction f = regTabPtr->readFunctionArray[attributeId];
AttributeHeader::init(&attributeHeader, attributeId, 0);
@@ -691,7 +706,7 @@ Dbtup::checkUpdateOfPrimaryKey(Uint32* updateBuffer, Tablerec* const regTabPtr)
tMaxRead = MAX_KEY_SIZE_IN_WORDS;
bool tmp = tXfrmFlag;
- tXfrmFlag = false;
+ tXfrmFlag = true;
ndbrequire((this->*f)(&keyReadBuffer[0], ahOut, attrDescriptor, attributeOffset));
tXfrmFlag = tmp;
ndbrequire(tOutBufIndex == ahOut->getDataSize());
diff --git a/ndb/src/kernel/vm/SimulatedBlock.cpp b/ndb/src/kernel/vm/SimulatedBlock.cpp
index d708052ca4e..4625cd43640 100644
--- a/ndb/src/kernel/vm/SimulatedBlock.cpp
+++ b/ndb/src/kernel/vm/SimulatedBlock.cpp
@@ -1868,49 +1868,9 @@ SimulatedBlock::xfrm_key(Uint32 tab, const Uint32* src,
while (i < noOfKeyAttr)
{
const KeyDescriptor::KeyAttr& keyAttr = desc->keyAttr[i];
-
- Uint32 srcBytes =
- AttributeDescriptor::getSizeInBytes(keyAttr.attributeDescriptor);
- Uint32 srcWords = (srcBytes + 3) / 4;
- Uint32 dstWords = ~0;
- uchar* dstPtr = (uchar*)&dst[dstPos];
- const uchar* srcPtr = (const uchar*)&src[srcPos];
- CHARSET_INFO* cs = keyAttr.charsetInfo;
-
- if (cs == NULL)
- {
- jam();
- memcpy(dstPtr, srcPtr, srcWords << 2);
- dstWords = srcWords;
- }
- else
- {
- jam();
- Uint32 typeId =
- AttributeDescriptor::getType(keyAttr.attributeDescriptor);
- Uint32 lb, len;
- bool ok = NdbSqlUtil::get_var_length(typeId, srcPtr, srcBytes, lb, len);
- ndbrequire(ok);
- Uint32 xmul = cs->strxfrm_multiply;
- if (xmul == 0)
- xmul = 1;
- /*
- * Varchar is really Char. End spaces do not matter. To get
- * same hash we blank-pad to maximum length via strnxfrm.
- * TODO use MySQL charset-aware hash function instead
- */
- Uint32 dstLen = xmul * (srcBytes - lb);
- ndbrequire(dstLen <= ((dstSize - dstPos) << 2));
- int n = NdbSqlUtil::strnxfrm_bug7284(cs, dstPtr, dstLen, srcPtr + lb, len);
- ndbrequire(n != -1);
- while ((n & 3) != 0)
- {
- dstPtr[n++] = 0;
- }
- dstWords = (n >> 2);
- }
- dstPos += dstWords;
- srcPos += srcWords;
+ Uint32 dstWords =
+ xfrm_attr(keyAttr.attributeDescriptor, keyAttr.charsetInfo,
+ src, srcPos, dst, dstPos, dstSize);
keyPartLen[i++] = dstWords;
}
@@ -1918,6 +1878,52 @@ SimulatedBlock::xfrm_key(Uint32 tab, const Uint32* src,
}
Uint32
+SimulatedBlock::xfrm_attr(Uint32 attrDesc, CHARSET_INFO* cs,
+ const Uint32* src, Uint32 & srcPos,
+ Uint32* dst, Uint32 & dstPos, Uint32 dstSize) const
+{
+ Uint32 srcBytes = AttributeDescriptor::getSizeInBytes(attrDesc);
+ Uint32 srcWords = (srcBytes + 3) / 4;
+ Uint32 dstWords = ~0;
+ uchar* dstPtr = (uchar*)&dst[dstPos];
+ const uchar* srcPtr = (const uchar*)&src[srcPos];
+
+ if (cs == NULL)
+ {
+ jam();
+ memcpy(dstPtr, srcPtr, srcWords << 2);
+ dstWords = srcWords;
+ }
+ else
+ {
+ jam();
+ Uint32 typeId = AttributeDescriptor::getType(attrDesc);
+ Uint32 lb, len;
+ bool ok = NdbSqlUtil::get_var_length(typeId, srcPtr, srcBytes, lb, len);
+ ndbrequire(ok);
+ Uint32 xmul = cs->strxfrm_multiply;
+ if (xmul == 0)
+ xmul = 1;
+ /*
+ * Varchar end-spaces are ignored in comparisons. To get same hash
+ * we blank-pad to maximum length via strnxfrm.
+ */
+ Uint32 dstLen = xmul * (srcBytes - lb);
+ ndbrequire(dstLen <= ((dstSize - dstPos) << 2));
+ int n = NdbSqlUtil::strnxfrm_bug7284(cs, dstPtr, dstLen, srcPtr + lb, len);
+ ndbrequire(n != -1);
+ while ((n & 3) != 0)
+ {
+ dstPtr[n++] = 0;
+ }
+ dstWords = (n >> 2);
+ }
+ dstPos += dstWords;
+ srcPos += srcWords;
+ return dstWords;
+}
+
+Uint32
SimulatedBlock::create_distr_key(Uint32 tableId,
Uint32 *data,
const Uint32
diff --git a/ndb/src/kernel/vm/SimulatedBlock.hpp b/ndb/src/kernel/vm/SimulatedBlock.hpp
index ce77fa916d8..b7bd8c57ee8 100644
--- a/ndb/src/kernel/vm/SimulatedBlock.hpp
+++ b/ndb/src/kernel/vm/SimulatedBlock.hpp
@@ -395,8 +395,12 @@ protected:
* @return length
*/
Uint32 xfrm_key(Uint32 tab, const Uint32* src,
- Uint32 *dst, Uint32 dstLen,
+ Uint32 *dst, Uint32 dstSize,
Uint32 keyPartLen[MAX_ATTRIBUTES_IN_INDEX]) const;
+
+ Uint32 xfrm_attr(Uint32 attrDesc, CHARSET_INFO* cs,
+ const Uint32* src, Uint32 & srcPos,
+ Uint32* dst, Uint32 & dstPos, Uint32 dstSize) const;
/**
*
diff --git a/ndb/src/ndbapi/NdbImpl.hpp b/ndb/src/ndbapi/NdbImpl.hpp
index d50f1fa84fe..c668533457d 100644
--- a/ndb/src/ndbapi/NdbImpl.hpp
+++ b/ndb/src/ndbapi/NdbImpl.hpp
@@ -89,11 +89,9 @@ public:
/**
* NOTE free lists must be _after_ theNdbObjectIdMap take
* assure that destructors are run in correct order
+ * NOTE these has to be in this specific order to make destructor run in
+ * correct order
*/
- Ndb_free_list_t<NdbTransaction> theConIdleList;
- Ndb_free_list_t<NdbOperation> theOpIdleList;
- Ndb_free_list_t<NdbIndexScanOperation> theScanOpIdleList;
- Ndb_free_list_t<NdbIndexOperation> theIndexOpIdleList;
Ndb_free_list_t<NdbRecAttr> theRecAttrIdleList;
Ndb_free_list_t<NdbApiSignal> theSignalIdleList;
Ndb_free_list_t<NdbLabel> theLabelList;
@@ -102,6 +100,10 @@ public:
Ndb_free_list_t<NdbCall> theCallList;
Ndb_free_list_t<NdbBlob> theNdbBlobIdleList;
Ndb_free_list_t<NdbReceiver> theScanList;
+ Ndb_free_list_t<NdbIndexScanOperation> theScanOpIdleList;
+ Ndb_free_list_t<NdbOperation> theOpIdleList;
+ Ndb_free_list_t<NdbIndexOperation> theIndexOpIdleList;
+ Ndb_free_list_t<NdbTransaction> theConIdleList;
};
#ifdef VM_TRACE
diff --git a/ndb/src/ndbapi/NdbRecAttr.cpp b/ndb/src/ndbapi/NdbRecAttr.cpp
index 2245707bf65..771da56523c 100644
--- a/ndb/src/ndbapi/NdbRecAttr.cpp
+++ b/ndb/src/ndbapi/NdbRecAttr.cpp
@@ -24,6 +24,7 @@
NdbRecAttr::NdbRecAttr(Ndb*)
{
+ theStorageX = 0;
init();
}
@@ -53,6 +54,9 @@ NdbRecAttr::setup(const NdbColumnImpl* anAttrInfo, char* aValue)
theNULLind = 0;
m_nullable = anAttrInfo->m_nullable;
+ if (theStorageX)
+ delete[] theStorageX;
+
// check alignment to signal data
// a future version could check alignment per data type as well
diff --git a/ndb/tools/ndb_size.pl b/ndb/tools/ndb_size.pl
index 64a20423636..ece0901e0b2 100644
--- a/ndb/tools/ndb_size.pl
+++ b/ndb/tools/ndb_size.pl
@@ -26,24 +26,33 @@ use HTML::Template;
# BUGS
# ----
# - enum/set is 0 byte storage! Woah - efficient!
+# - DECIMAL is 0 byte storage. A bit too efficient.
# - some float stores come out weird (when there's a comma e.g. 'float(4,1)')
# - no disk data values
# - computes the storage requirements of views (and probably MERGE)
# - ignores character sets.
my $template = HTML::Template->new(filename => 'ndb_size.tmpl',
- die_on_bad_params => 0);
+ die_on_bad_params => 0)
+ or die "Could not open ndb_size.tmpl.";
my $dbh;
+if(@ARGV < 3 || $ARGV[0] eq '--usage' || $ARGV[0] eq '--help')
+{
+ print STDERR "Usage:\n";
+ print STDERR "\tndb_size.pl database hostname user password\n\n";
+ print STDERR "If you need to specify a port number, use host:port\n\n";
+ exit(1);
+}
+
{
my $database= $ARGV[0];
my $hostname= $ARGV[1];
- my $port= $ARGV[2];
- my $user= $ARGV[3];
- my $password= $ARGV[4];
- my $dsn = "DBI:mysql:database=$database;host=$hostname;port=$port";
- $dbh= DBI->connect($dsn, $user, $password);
+ my $user= $ARGV[2];
+ my $password= $ARGV[3];
+ my $dsn = "DBI:mysql:database=$database;host=$hostname";
+ $dbh= DBI->connect($dsn, $user, $password) or exit(1);
$template->param(db => $database);
$template->param(dsn => $dsn);
}
@@ -55,6 +64,14 @@ my $tables = $dbh->selectall_arrayref("show tables");
my @table_size;
+my @dbDataMemory;
+my @dbIndexMemory;
+my @NoOfAttributes;
+my @NoOfIndexes;
+my @NoOfTables;
+$NoOfTables[$_]{val} = @{$tables} foreach 0..$#releases;
+
+
sub align {
my($to,@unaligned) = @_;
my @aligned;
@@ -68,9 +85,8 @@ foreach(@{$tables})
{
my $table= @{$_}[0];
my @columns;
- my $info= $dbh->selectall_hashref("describe ".$dbh->quote($table),"Field");
- my @count = $dbh->selectrow_array("select count(*) from "
- .$dbh->quote($table));
+ my $info= $dbh->selectall_hashref('describe `'.$table.'`',"Field");
+ my @count = $dbh->selectrow_array('select count(*) from `'.$table.'`');
my %columnsize; # used for index calculations
# We now work out the DataMemory usage
@@ -132,14 +148,17 @@ foreach(@{$tables})
my $fixed= 1+$size;
my @dynamic=$dbh->selectrow_array("select avg(length("
.$dbh->quote($name)
- .")) from ".$dbh->quote($table));
+ .")) from `".$table.'`');
$dynamic[0]=0 if !$dynamic[0];
@realsize= ($fixed,$fixed,ceil($dynamic[0]));
}
elsif($type =~ /binary/ || $type =~ /char/)
{@realsize=($size,$size,$size)}
elsif($type =~ /text/ || $type =~ /blob/)
- {@realsize=(256,256,1)} # FIXME check if 5.1 is correct
+ {
+ @realsize=(256,256,1);
+ $NoOfTables[$_]{val} += 1 foreach 0..$#releases; # blob uses table
+ } # FIXME check if 5.1 is correct
@realsize= align(4,@realsize);
@@ -166,7 +185,7 @@ foreach(@{$tables})
# we can still connect to pre-5.0 mysqlds.
my %indexes;
{
- my $sth= $dbh->prepare("show index from "$dbh->quote($table));
+ my $sth= $dbh->prepare("show index from `".$table.'`');
$sth->execute;
while(my $i = $sth->fetchrow_hashref)
{
@@ -257,7 +276,51 @@ foreach(@{$tables})
IndexMemory=>\@IndexMemory,
};
+
+ $dbDataMemory[$_]{val} += $DataMemory[$_]{val} foreach 0..$#releases;
+ $dbIndexMemory[$_]{val} += $IndexMemory[$_]{val} foreach 0..$#releases;
+ $NoOfAttributes[$_]{val} += @columns foreach 0..$#releases;
+ $NoOfIndexes[$_]{val} += @indexes foreach 0..$#releases;
+}
+
+my @NoOfTriggers;
+# for unique hash indexes
+$NoOfTriggers[$_]{val} += $NoOfIndexes[$_]{val}*3 foreach 0..$#releases;
+# for ordered index
+$NoOfTriggers[$_]{val} += $NoOfIndexes[$_]{val} foreach 0..$#releases;
+
+my @ParamMemory;
+foreach (0..$#releases) {
+ $ParamMemory[0]{releases}[$_]{val}= POSIX::ceil(200*$NoOfAttributes[$_]{val}/1024);
+ $ParamMemory[0]{name}= 'Attributes';
+
+ $ParamMemory[1]{releases}[$_]{val}= 20*$NoOfTables[$_]{val};
+ $ParamMemory[1]{name}= 'Tables';
+
+ $ParamMemory[2]{releases}[$_]{val}= 10*$NoOfIndexes[$_]{val};
+ $ParamMemory[2]{name}= 'OrderedIndexes';
+
+ $ParamMemory[3]{releases}[$_]{val}= 15*$NoOfIndexes[$_]{val};
+ $ParamMemory[3]{name}= 'UniqueHashIndexes';
}
$template->param(tables => \@table_size);
+$template->param(Parameters => [{name=>'DataMemory (kb)',
+ releases=>\@dbDataMemory},
+ {name=>'IndexMemory (kb)',
+ releases=>\@dbIndexMemory},
+ {name=>'MaxNoOfTables',
+ releases=>\@NoOfTables},
+ {name=>'MaxNoOfAttributes',
+ releases=>\@NoOfAttributes},
+ {name=>'MaxNoOfOrderedIndexes',
+ releases=>\@NoOfIndexes},
+ {name=>'MaxNoOfUniqueHashIndexes',
+ releases=>\@NoOfIndexes},
+ {name=>'MaxNoOfTriggers',
+ releases=>\@NoOfTriggers}
+ ]
+ );
+$template->param(ParamMemory => \@ParamMemory);
+
print $template->output;
diff --git a/ndb/tools/ndb_size.tmpl b/ndb/tools/ndb_size.tmpl
index d83d5d2c6af..dc02b5a5970 100644
--- a/ndb/tools/ndb_size.tmpl
+++ b/ndb/tools/ndb_size.tmpl
@@ -13,18 +13,58 @@ td,th { border: 1px solid black }
<h1>MySQL Cluster analysis for <TMPL_VAR NAME="db" escape="html"></h1>
<p>This is an automated analysis of the <TMPL_VAR NAME="DSN" escape="html"> database for migration into <a href="http://www.mysql.com/">MySQL</a> Cluster. No warranty is made to the accuracy of the information.</p>
-<p>This information should be valid for MySQL 4.1</p>
+<p>This information should be valid for MySQL 4.1 and 5.0. Since 5.1 is not a final release yet, the numbers should be used as a guide only.</p>
+<h2>Parameter Settings</h2>
+<p><b>NOTE</b> the configuration parameters below do not take into account system tables and other requirements.</p>
+<table>
+ <tr>
+ <th>Parameter</th>
+ <TMPL_LOOP NAME=releases>
+ <th><TMPL_VAR NAME=rel></th>
+ </TMPL_LOOP>
+ </tr>
+<TMPL_LOOP NAME=Parameters>
+ <tr>
+ <td><TMPL_VAR NAME=name></td>
+ <TMPL_LOOP NAME=releases>
+ <td><TMPL_VAR NAME=val></td>
+ </TMPL_LOOP>
+ </tr>
+</TMPL_LOOP>
+</table>
+
+<h2>Memory usage because of parameters</h2>
+
+<p>Usage is in kilobytes. Actual usage will vary as you should set the parameters larger than those listed in the table above.</p>
+<table>
+ <tr>
+ <th>Parameter</th>
+ <TMPL_LOOP NAME=releases>
+ <th><TMPL_VAR NAME=rel></th>
+ </TMPL_LOOP>
+ </tr>
+<TMPL_LOOP NAME=ParamMemory>
+ <tr>
+ <td><TMPL_VAR NAME=name></td>
+ <TMPL_LOOP NAME=releases>
+ <td><TMPL_VAR NAME=val></td>
+ </TMPL_LOOP>
+ </tr>
+</TMPL_LOOP>
+</table>
+
+<h2>Table List</h2>
<ul>
<TMPL_LOOP NAME="tables">
-<li><TMPL_VAR NAME="table"></li>
+<li><a href="#<TMPL_VAR NAME="table">"><TMPL_VAR NAME="table"></a></li>
</TMPL_LOOP>
</ul>
<hr/>
<TMPL_LOOP NAME="tables">
-<h2><TMPL_VAR NAME="table"></h2>
+<h2><a name="<TMPL_VAR NAME="table">"><TMPL_VAR NAME="table"></a></h2>
<table>
<tr>
<th>Column</th>