4176 John David Duncan 2011-05-15
New TabSeparatedValues class
added:
storage/ndb/memcache/include/TabSeparatedValues.h
storage/ndb/memcache/src/TabSeparatedValues.cc
storage/ndb/memcache/unit/tsv.cc
modified:
storage/ndb/memcache/Makefile.am
storage/ndb/memcache/unit/Makefile.am
storage/ndb/memcache/unit/all_tests.h
storage/ndb/memcache/unit/harness.cc
4175 John David Duncan 2011-05-15
Support CHAR
modified:
storage/ndb/memcache/src/DataTypeHandler.cc
4174 John David Duncan 2011-05-15
Refactor DataTypeHandler so that readFromNdb() and writeToNdb() return an int -- the length read/written, or < 0 for error.
modified:
storage/ndb/memcache/include/DataTypeHandler.h
storage/ndb/memcache/include/Operation.h
storage/ndb/memcache/include/Record.h
storage/ndb/memcache/src/DataTypeHandler.cc
storage/ndb/memcache/src/Record.cc
4173 John David Duncan 2011-05-15
Improvements to unit-test framework
modified:
storage/ndb/memcache/unit/all_tests.h
storage/ndb/memcache/unit/connpool.cc
storage/ndb/memcache/unit/harness.cc
4172 John David Duncan 2011-05-15
ndb_types.h is available; just include it.
modified:
storage/ndb/memcache/include/ndbmemcache_config.h
4171 John David Duncan 2011-04-30
Fix for stack-corrupting, crashing bug when reading uint64 columns.
modified:
storage/ndb/memcache/src/Record.cc
=== modified file 'storage/ndb/memcache/Makefile.am'
--- a/storage/ndb/memcache/Makefile.am 2011-04-26 07:24:58 +0000
+++ b/storage/ndb/memcache/Makefile.am 2011-05-16 06:14:51 +0000
@@ -37,6 +37,7 @@ ndb_engine_la_SOURCES= \
src/QueryPlan.cc \
src/Record.cc \
src/TableSpec.cc \
+ src/TabSeparatedValues.cc \
src/workqueue.c \
src/schedulers/Stockholm.h \
src/schedulers/Stockholm.cc \
=== modified file 'storage/ndb/memcache/include/DataTypeHandler.h'
--- a/storage/ndb/memcache/include/DataTypeHandler.h 2011-03-30 06:54:53 +0000
+++ b/storage/ndb/memcache/include/DataTypeHandler.h 2011-05-16 05:49:22 +0000
@@ -36,25 +36,24 @@
/* Return status codes from some of the functions:
*/
-// TODO: Return an int: the encoded/read length, or < 0 on error.
-enum TypeHandlerStatus {
- DTH_OK = 0,
- DTH_NOT_SUPPORTED,
- DTH_VALUE_TOO_LONG
+
+enum { /* These can be returned by readFromNdb() or writeToNdb() */
+ DTH_NOT_SUPPORTED = -1,
+ DTH_VALUE_TOO_LONG = -2
};
/* DataTypeHandler interface:
*/
typedef struct {
- // String Readers
- TypeHandlerStatus (*readFromNdb)(const NdbDictionary::Column *col, size_t &len,
- char * &str, const void * const buf);
+ // String Readers. Returns length read.
+ int (*readFromNdb)(const NdbDictionary::Column *col,
+ char * &str, const void * const buf);
size_t (*getStringifiedLength)(const NdbDictionary::Column *col,
const void * const buf);
- // String Writer
- TypeHandlerStatus (*writeToNdb)(const NdbDictionary::Column *col, size_t len,
- size_t offset, const char *str, void * const buf);
+ // String Writer. Returns length written or < 0 for error.
+ int (*writeToNdb)(const NdbDictionary::Column *col, size_t len,
+ size_t offset, const char *str, void * const buf);
// For an integer column, this holds the int's size in bytes. Otherwise zero.
int direct_int_size;
=== modified file 'storage/ndb/memcache/include/Operation.h'
--- a/storage/ndb/memcache/include/Operation.h 2011-04-07 11:20:56 +0000
+++ b/storage/ndb/memcache/include/Operation.h 2011-05-16 05:49:22 +0000
@@ -134,8 +134,8 @@ inline void Operation::clearKeyNullBits(
}
inline bool Operation::setKeyPart(int idx, const char *strval, size_t strlen) {
- TypeHandlerStatus s = plan->key_record->encode(idx, strval, strlen, key_buffer);
- return (s == DTH_OK);
+ int s = plan->key_record->encode(idx, strval, strlen, key_buffer);
+ return (s > 0);
}
inline bool Operation::setKeyPartInt(int idx, int value) {
@@ -157,8 +157,8 @@ inline void Operation::clearNullBits() {
}
inline bool Operation::setColumn(int idx, const char *strval, size_t strlen) {
- TypeHandlerStatus s = record->encode(idx, strval, strlen, buffer);
- return (s == DTH_OK);
+ int s = record->encode(idx, strval, strlen, buffer);
+ return (s > 0);
}
inline bool Operation::setColumnInt(int idx, int value) {
=== modified file 'storage/ndb/memcache/include/Record.h'
--- a/storage/ndb/memcache/include/Record.h 2011-04-07 11:20:56 +0000
+++ b/storage/ndb/memcache/include/Record.h 2011-05-16 05:49:22 +0000
@@ -76,7 +76,7 @@ class Record {
int getIntValue(int idx, char *data) const;
bool setUint64Value(int idx, Uint64 value, char *buffer) const;
Uint64 getUint64Value(int idx, char *data) const;
- TypeHandlerStatus encode(int idx, const char *key, int nkey, char *buffer) const;
+ int encode(int idx, const char *key, int nkey, char *buffer) const;
size_t getStringifiedLength(char *data) const;
bool decodeNoCopy(int idx, char **dest_ptr, size_t *len_ptr,
const char * const src) const;
=== added file 'storage/ndb/memcache/include/TabSeparatedValues.h'
--- a/storage/ndb/memcache/include/TabSeparatedValues.h 1970-01-01 00:00:00 +0000
+++ b/storage/ndb/memcache/include/TabSeparatedValues.h 2011-05-16 06:14:51 +0000
@@ -0,0 +1,55 @@
+/*
+ Copyright (c) 2011, 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 the Free Software Foundation; version 2 of
+ the License.
+
+ 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., 51 Franklin St, Fifth Floor, Boston, MA
+ 02110-1301 USA
+ */
+#ifndef NDBMEMCACHE_TABSEP_H
+#define NDBMEMCACHE_TABSEP_H
+
+#include "ndbmemcache_config.h"
+#include "Record.h"
+
+class TabSeparatedValues {
+ public:
+ TabSeparatedValues(const char * string, Uint32 max_parts, size_t length);
+ int advance(); // inlined
+ const char * getPointer(); // inlined
+ size_t getLength(); // inlined
+
+ private:
+ int index;
+ int parts;
+ const char * pointers[MAX_VAL_COLUMNS];
+ size_t lengths[MAX_VAL_COLUMNS];
+ int find_tab(const char *, int) const;
+};
+
+
+inline int TabSeparatedValues::advance() {
+ return ++index < parts ? 1 : 0;
+}
+
+inline const char * TabSeparatedValues::getPointer() {
+ return pointers[index];
+}
+
+inline size_t TabSeparatedValues::getLength() {
+ return lengths[index];
+}
+
+
+#endif
=== modified file 'storage/ndb/memcache/include/ndbmemcache_config.h'
--- a/storage/ndb/memcache/include/ndbmemcache_config.h 2011-04-21 10:45:07 +0000
+++ b/storage/ndb/memcache/include/ndbmemcache_config.h 2011-05-16 05:21:20 +0000
@@ -15,26 +15,10 @@
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
-/**
- * @file ndb_types.h
- */
-
#ifndef MEMCACHED_CONFIG_H
#define MEMCACHED_CONFIG_H
#include <config.h>
#include <ndb_types.h>
-//typedef Uint64 uint64_t;
-//typedef Uint32 uint32_t;
-
-//typedef Int64 int64_t;
-/*
-typedef signed char Int8;
-typedef unsigned char Uint8;
-typedef signed short Int16;
-typedef unsigned short Uint16;
-typedef signed int Int32;
-typedef unsigned int Uint32;
-*/
#endif // MEMCACHED_CONFIG_H
=== modified file 'storage/ndb/memcache/src/DataTypeHandler.cc'
--- a/storage/ndb/memcache/src/DataTypeHandler.cc 2011-03-30 06:54:53 +0000
+++ b/storage/ndb/memcache/src/DataTypeHandler.cc 2011-05-16 06:07:15 +0000
@@ -31,58 +31,77 @@
#include "DataTypeHandler.h"
#include "debug.h"
-#define DECODE_ARGS const NdbDictionary::Column *, size_t &, char * &, const void *
+#define DECODE_ARGS const NdbDictionary::Column *, char * &, const void *
#define SFDLEN_ARGS const NdbDictionary::Column *, const void *
-#define WRITE_ARGS const NdbDictionary::Column *, size_t, size_t, const char *, void *
+#define WRITE_ARGS const NdbDictionary::Column *, size_t, size_t, const char *, void *
-typedef TypeHandlerStatus impl_readFromNdb(DECODE_ARGS);
-typedef size_t impl_getStringifiedLength(SFDLEN_ARGS);
-typedef TypeHandlerStatus impl_writeToNdb(WRITE_ARGS);
+typedef int impl_readFromNdb(DECODE_ARGS);
+typedef size_t impl_getStringifiedLength(SFDLEN_ARGS);
+typedef int impl_writeToNdb(WRITE_ARGS);
/* Implementations for readFromNdb() */
impl_readFromNdb dth_decode_varchar;
impl_readFromNdb dth_decode_longvarchar;
+impl_readFromNdb dth_decode_char;
+impl_readFromNdb dth_decode_char1;
impl_readFromNdb dth_decode_int;
impl_readFromNdb dth_decode_ubigint;
-impl_readFromNdb dth_decode_char1;
/* Implementations for impl_getStringifiedLength() */
-impl_getStringifiedLength dth_sfdlen_varchar;
-impl_getStringifiedLength dth_sfdlen_longvarchar;
-impl_getStringifiedLength dth_sfdlen_int;
-impl_getStringifiedLength dth_sfdlen_ubigint;
-impl_getStringifiedLength dth_sfdlen_char1;
+impl_getStringifiedLength dth_length_varchar;
+impl_getStringifiedLength dth_length_longvarchar;
+impl_getStringifiedLength dth_length_char;
+impl_getStringifiedLength dth_length_char1;
+impl_getStringifiedLength dth_length_int;
+impl_getStringifiedLength dth_length_ubigint;
/* Implementations for writeToNdb() */
impl_writeToNdb dth_encode_varchar;
impl_writeToNdb dth_encode_longvarchar;
+impl_writeToNdb dth_encode_char;
+impl_writeToNdb dth_encode_char1;
impl_writeToNdb dth_encode_int;
impl_writeToNdb dth_encode_ubigint;
-impl_writeToNdb dth_encode_char1;
/***** Singleton Handlers *****/
DataTypeHandler Handler_Varchar = {
- dth_decode_varchar,
- dth_sfdlen_varchar,
- dth_encode_varchar,
- 0,
- true
+ dth_decode_varchar, // readFromNdb()
+ dth_length_varchar, // getStringifiedLength()
+ dth_encode_varchar, // writeToNdb()
+ 0, // direct_int_size
+ true // contains_string
};
DataTypeHandler Handler_LongVarchar = {
dth_decode_longvarchar,
- dth_sfdlen_longvarchar,
+ dth_length_longvarchar,
dth_encode_longvarchar,
0,
true
};
+DataTypeHandler Handler_Char = {
+ dth_decode_char, // readFromNdb()
+ dth_length_char, // getStringifiedLength()
+ dth_encode_char, // writeToNdb()
+ 0, // direct_int_size
+ true // contains_string
+};
+
+DataTypeHandler Handler_enum = { /* NDB sees ENUM columns as CHAR(1) */
+ dth_decode_char1,
+ dth_length_char1,
+ dth_encode_char1,
+ 1,
+ false
+};
+
DataTypeHandler Handler_Int = {
dth_decode_int,
- dth_sfdlen_int,
+ dth_length_int,
dth_encode_int,
4,
false
@@ -90,19 +109,12 @@ DataTypeHandler Handler_Int = {
DataTypeHandler Handler_BigIntUnsigned = {
dth_decode_ubigint,
- dth_sfdlen_ubigint,
+ dth_length_ubigint,
dth_encode_ubigint,
8,
false
};
-DataTypeHandler Handler_enum = { /* NDB sees ENUM columns as CHAR(1) */
- dth_decode_char1,
- dth_sfdlen_char1,
- dth_encode_char1,
- 1,
- false
-};
/*
@@ -128,7 +140,7 @@ DataTypeHandler * getDataTypeHandlerForC
case NdbDictionary::Column::Char:
if(col->getLength() == 1) return & Handler_enum;
- /* fallthrough. TODO: support CHAR */
+ else return & Handler_Char;
default:
return NULL;
@@ -171,25 +183,23 @@ size_t getColumnRecordSize(const NdbDict
/******************* IMPLEMENTATIONS *******************/
/***** VARCHAR *****/
-TypeHandlerStatus dth_decode_varchar(const NdbDictionary::Column *col,
- size_t &len, char * &str,
- const void *buf) {
- len = dth_sfdlen_varchar(col, buf);
+int dth_decode_varchar(const NdbDictionary::Column *col,
+ char * &str, const void *buf) {
+ size_t len = dth_length_varchar(col, buf);
str = ((char *) buf) + 1;
- return DTH_OK;
+ return len;
}
-size_t dth_sfdlen_varchar(const NdbDictionary::Column *col, const void *buf) {
+size_t dth_length_varchar(const NdbDictionary::Column *col, const void *buf) {
/* Return the actual length of the value string */
uint8_t * length_byte = (uint8_t *) buf;
return (size_t) (*length_byte);
}
-TypeHandlerStatus dth_encode_varchar(const NdbDictionary::Column *col,
- size_t len, size_t offset,
- const char *str, void *buf) {
+int dth_encode_varchar(const NdbDictionary::Column *col,
+ size_t len, size_t offset, const char *str, void *buf) {
size_t total_len = len + offset;
uint8_t * length_byte = (uint8_t *) buf;
char *char_buffer = ((char *) buf) + 1 + offset;
@@ -203,22 +213,21 @@ TypeHandlerStatus dth_encode_varchar(con
/* Copy string value into buffer */
strncpy(char_buffer, str, len);
- return DTH_OK;
+ return len;
}
/***** LONGVARCHAR *****/
-TypeHandlerStatus dth_decode_longvarchar(const NdbDictionary::Column *col,
- size_t &len, char * &str,
- const void *buf) {
- len = dth_sfdlen_longvarchar(col, buf);
+int dth_decode_longvarchar(const NdbDictionary::Column *col,
+ char * &str, const void *buf) {
+ size_t len = dth_length_longvarchar(col, buf);
str = ((char *) buf) + 2;
- return DTH_OK;
+ return len;
}
-size_t dth_sfdlen_longvarchar(const NdbDictionary::Column *col, const void *buf) {
+size_t dth_length_longvarchar(const NdbDictionary::Column *col, const void *buf) {
/* Return the actual length of the value string */
uint8_t * length_byte_1 = (uint8_t *) buf;
uint8_t * length_byte_2 = ((uint8_t *) buf) + 1;
@@ -227,7 +236,7 @@ size_t dth_sfdlen_longvarchar(const NdbD
}
-TypeHandlerStatus dth_encode_longvarchar(const NdbDictionary::Column *col,
+int dth_encode_longvarchar(const NdbDictionary::Column *col,
size_t len, size_t offset,
const char *str, void *buf) {
char *cbuf = ((char *) buf);
@@ -246,20 +255,41 @@ TypeHandlerStatus dth_encode_longvarchar
/* Copy string value into buffer */
strncpy(dest, str, len);
- return DTH_OK;
+ return len;
}
+/***** CHAR *****/
+int dth_decode_char(const NdbDictionary::Column *col,
+ char * &str, const void *buf) {
+ *str = * (char *) buf;
+ // TODO: is it null-padded? space-padded?
+ return col->getLength();
+}
+
+size_t dth_length_char(const NdbDictionary::Column *col, const void *buf) {
+ return col->getLength();
+}
+
+int dth_encode_char(const NdbDictionary::Column *col,
+ size_t len, size_t offset, const char *str, void *buf) {
+ char *cbuf = ((char *) buf);
+ char *dest = cbuf + offset;
+
+ if(len > col->getLength()) return DTH_VALUE_TOO_LONG;
+
+ memcpy(dest, str, len);
+ return len;
+}
+
/***** INT *****/
-TypeHandlerStatus dth_decode_int(const NdbDictionary::Column *col, size_t &len,
- char * &str, const void *buf) {
- len = sprintf(str, "%d",* (int *) buf) + 1; // +1 for null terminator
-
- return DTH_OK;
+int dth_decode_int(const NdbDictionary::Column *col,
+ char * &str, const void *buf) {
+ return sprintf(str, "%d",* (int *) buf) + 1; // +1 for null terminator
}
-size_t dth_sfdlen_int(const NdbDictionary::Column *col, const void *buf) {
+size_t dth_length_int(const NdbDictionary::Column *col, const void *buf) {
int i = *((int *) buf);
int len = ( i < 0) ? 2 : 1;
for( ; i > 0 ; len++) i = i / 10;
@@ -267,27 +297,24 @@ size_t dth_sfdlen_int(const NdbDictionar
}
-TypeHandlerStatus dth_encode_int(const NdbDictionary::Column *col,
- size_t len, size_t offset,
- const char *str, void *buf) {
+int dth_encode_int(const NdbDictionary::Column *col,
+ size_t len, size_t offset, const char *str, void *buf) {
assert(offset == 0);
int *ibuf = (int *) buf;
- *ibuf = strtol(str, NULL, 10);
-
- return DTH_OK;
+ *ibuf = strtol(str, NULL, 10);
+
+ return len;
}
/***** BIGINT UNSIGNED *****/
-TypeHandlerStatus dth_decode_ubigint(const NdbDictionary::Column *col, size_t &len,
- char * &str, const void *buf) {
- len = sprintf(str, "%"PRIu64,* (uint64_t *) buf) + 1; // +1 for null
-
- return DTH_OK;
+int dth_decode_ubigint(const NdbDictionary::Column *col,
+ char * &str, const void *buf) {
+ return sprintf(str, "%"PRIu64,* (Uint64 *) buf) + 1; // +1 for null
}
-size_t dth_sfdlen_ubigint(const NdbDictionary::Column *col, const void *buf) {
+size_t dth_length_ubigint(const NdbDictionary::Column *col, const void *buf) {
int i = *((uint64_t *) buf);
int len = ( i < 0) ? 2 : 1;
for( ; i > 0 ; len++) i = i / 10;
@@ -295,37 +322,33 @@ size_t dth_sfdlen_ubigint(const NdbDicti
}
-TypeHandlerStatus dth_encode_ubigint(const NdbDictionary::Column *col,
- size_t len, size_t offset,
- const char *str, void *buf) {
+int dth_encode_ubigint(const NdbDictionary::Column *col,
+ size_t len, size_t offset, const char *str, void *buf) {
assert(offset == 0);
uint64_t *ibuf = (uint64_t *) buf;
*ibuf = strtoull(str, NULL, 10);
- return DTH_OK;
+ return len;
}
/***** ENUM *****/
-TypeHandlerStatus dth_decode_char1(const NdbDictionary::Column *col, size_t &len,
- char * &str, const void *buf) {
- *str = * (char *) buf;
- len = 1;
-
- return DTH_OK;
+int dth_decode_char1(const NdbDictionary::Column *col,
+ char * &str, const void *buf) {
+ *str = * (char *) buf;
+ return 1;
}
-size_t dth_sfdlen_char1(const NdbDictionary::Column *col, const void *buf) {
- return 1;
+size_t dth_length_char1(const NdbDictionary::Column *col, const void *buf) {
+ return 1;
}
-TypeHandlerStatus dth_encode_char1(const NdbDictionary::Column *col,
- size_t len, size_t offset,
- const char *str, void *buf) {
+int dth_encode_char1(const NdbDictionary::Column *col,
+ size_t len, size_t offset, const char *str, void *buf) {
assert(offset == 0);
char *cbuf = (char *) buf;
*cbuf = *str;
- return DTH_OK;
+ return 1;
}
=== modified file 'storage/ndb/memcache/src/Record.cc'
--- a/storage/ndb/memcache/src/Record.cc 2011-04-30 14:20:42 +0000
+++ b/storage/ndb/memcache/src/Record.cc 2011-05-16 05:49:22 +0000
@@ -149,7 +149,7 @@ bool Record::complete(NdbDictionary::Dic
bool Record::appendCRLF(int idx, size_t len, char *buffer) const {
if( handlers[col[idx]]->contains_string
&& handlers[col[idx]]->writeToNdb(specs[col[idx]].column, 2, len, "\r\n", buffer)
- == DTH_OK)
+ >= 0)
{
return true;
}
@@ -164,7 +164,7 @@ bool Record::decodeNoCopy(int idx,
if(! handlers[col[idx]]->contains_string) return false;
const char * src_buffer = src + specs[col[idx]].offset;
- handlers[col[idx]]->readFromNdb(specs[col[idx]].column, *len, *dest, src_buffer);
+ *len = handlers[col[idx]]->readFromNdb(specs[col[idx]].column, *dest, src_buffer);
return true;
}
@@ -181,7 +181,7 @@ size_t Record::decodeCopy(int idx, char
else { /* Types other than VARCHAR */
/* this works but it's strange; something has to be sorted out here.
handlers[col[idx]] but specs[idx] ?? */
- handlers[col[idx]]->readFromNdb(specs[idx].column, out_len, dest, src_buffer);
+ out_len = handlers[col[idx]]->readFromNdb(specs[idx].column, dest, src_buffer);
}
*(dest + out_len) = 0; // terminating null; may be overwritten by a tab
return out_len;
@@ -234,7 +234,7 @@ Uint64 Record::getUint64Value(int idx, c
}
-TypeHandlerStatus Record::encode(int idx, const char *key, int nkey,
+int Record::encode(int idx, const char *key, int nkey,
char *buffer) const {
return handlers[col[idx]]->writeToNdb(specs[col[idx]].column, nkey, 0, key,
buffer + specs[col[idx]].offset);
=== added file 'storage/ndb/memcache/src/TabSeparatedValues.cc'
--- a/storage/ndb/memcache/src/TabSeparatedValues.cc 1970-01-01 00:00:00 +0000
+++ b/storage/ndb/memcache/src/TabSeparatedValues.cc 2011-05-16 06:14:51 +0000
@@ -0,0 +1,46 @@
+/*
+ Copyright (c) 2011, 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 the Free Software Foundation; version 2 of
+ the License.
+
+ 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., 51 Franklin St, Fifth Floor, Boston, MA
+ 02110-1301 USA
+*/
+
+#include <assert.h>
+
+#include "TabSeparatedValues.h"
+
+TabSeparatedValues::TabSeparatedValues(const char *string, Uint32 max_parts, size_t length) :
+ parts(0), index(0)
+{
+ size_t parsed_len = 0;
+
+ assert(max_parts < MAX_VAL_COLUMNS);
+
+ while(parsed_len <= length && parts < max_parts) {
+ const char *s = string + parsed_len;
+ pointers[parts] = s;
+ lengths[parts] = find_tab(s, length - parsed_len);
+ parsed_len += lengths[parts] + 1;
+ parts++;
+ }
+}
+
+
+int TabSeparatedValues::find_tab(const char *s, int remaining) const {
+ int r;
+ for(r = 0; r < remaining && *(s+r) != '\t' && *(s+r) != '\0'; r++);
+ return r;
+}
=== modified file 'storage/ndb/memcache/unit/Makefile.am'
--- a/storage/ndb/memcache/unit/Makefile.am 2011-04-27 04:28:04 +0000
+++ b/storage/ndb/memcache/unit/Makefile.am 2011-05-16 06:14:51 +0000
@@ -36,7 +36,8 @@ run_unit_tests_SOURCES = harness.cc \
casbits.cc \
incr.cc \
alloc.cc \
- connpool.cc
+ connpool.cc \
+ tsv.cc
run_unit_tests_CFLAGS = -g -O0 \
-I${top_srcdir}/storage/ndb/memcache \
@@ -56,6 +57,7 @@ run_unit_tests_LDADD = ../ndb_engine_la-
../ndb_engine_la-Record.lo \
../ndb_engine_la-Stockholm.lo \
../ndb_engine_la-TableSpec.lo \
+ ../ndb_engine_la-TabSeparatedValues.lo \
../ndb_engine_la-assoc.lo \
../ndb_engine_la-atomics.lo \
../ndb_engine_la-debug.lo \
=== modified file 'storage/ndb/memcache/unit/all_tests.h'
--- a/storage/ndb/memcache/unit/all_tests.h 2011-03-30 06:54:53 +0000
+++ b/storage/ndb/memcache/unit/all_tests.h 2011-05-16 06:14:51 +0000
@@ -24,19 +24,25 @@
#include "QueryPlan.h"
#include "Operation.h"
-#define require(x) if(!(x)) return 0;
-#define pass return 1;
+#define require(x) if(!(x)) return __LINE__;
+#define pass return 0;
#define detail(v, fmt, ...) if(v) printf (fmt, ## __VA_ARGS__)
#define RESULT getNdbError().code
+#define REQ_NONE 0
+#define REQ_NDB_CONNECTION 1
+#define REQ_DEMO_TABLE 2
+
void delete_row(QueryPlan *plan, const char * key, int verbose);
typedef int TESTCASE(QueryPlan *plan, int verbose);
struct test_item {
+ int enabled;
const char *name;
TESTCASE *function;
+ int requires;
};
TESTCASE run_cas_test;
@@ -44,16 +50,24 @@ TESTCASE test_cas_bitshifts;
TESTCASE run_incr_test;
TESTCASE run_allocator_test;
TESTCASE run_pool_test;
+TESTCASE run_tsv_test;
#ifdef HARNESS
struct test_item all_tests[] = {
- { "cas operation", run_cas_test },
- { "cas bitshifting", test_cas_bitshifts },
- { "incr operation", run_incr_test },
- { "allocator", run_allocator_test },
- { "pool", run_pool_test },
- { NULL, NULL }
+ { 1, "cas operation", run_cas_test, REQ_DEMO_TABLE },
+ { 1, "cas bitshifting", test_cas_bitshifts, REQ_NONE },
+ { 1, "incr operation", run_incr_test, REQ_DEMO_TABLE },
+ { 1, "allocator", run_allocator_test, REQ_NONE },
+ { 0, "pool", run_pool_test, REQ_NDB_CONNECTION },
+ { 1, "tsv", run_tsv_test, REQ_NONE },
+ { 0, NULL, NULL, NULL }
+};
+
+
+const char * requirements[3] =
+{
+ "none", "ndb connection", "demo_table"
};
#else
=== modified file 'storage/ndb/memcache/unit/connpool.cc'
--- a/storage/ndb/memcache/unit/connpool.cc 2011-03-30 06:54:53 +0000
+++ b/storage/ndb/memcache/unit/connpool.cc 2011-05-16 05:37:57 +0000
@@ -28,7 +28,6 @@ int run_pool_test(QueryPlan *plan, int v
int r;
Ndb_cluster_connection &main_conn = plan->db->get_ndb_cluster_connection();
-
/* The pooled connection */
Ndb_cluster_connection * nc = new Ndb_cluster_connection(connect_string, & main_conn);
=== modified file 'storage/ndb/memcache/unit/harness.cc'
--- a/storage/ndb/memcache/unit/harness.cc 2011-04-19 01:16:36 +0000
+++ b/storage/ndb/memcache/unit/harness.cc 2011-05-16 06:14:51 +0000
@@ -26,10 +26,9 @@
#define HARNESS 1
#include "all_tests.h"
-/*** usage: ./run_unit_tests [connectstring] [test-id]
- These tests require a running cluster.
+/*** These tests require a running cluster.
Some of them require the ndbmemcache.demo_table to exist.
- If test-id is supplied, run one test verbosely;
+ If a particular test-id is supplied, run one test verbosely;
otherwise run all tests and indicate pass or fail.
***/
@@ -39,32 +38,43 @@ extern EXTENSION_LOGGER_DESCRIPTOR *logg
Ndb_cluster_connection * connect(const char *);
+int list_tests(void);
+int usage(char *);
+
int main(int argc, char *argv[]) {
+ connect_string = NULL;
int test_number = -1;
char * test_name = 0;
- if(argc > 1) connect_string = argv[1];
- if(argc > 2) {
- test_number = atoi(argv[2]);
- if(test_number) test_number -= 1;
- else test_name = argv[2];
- }
-
- ndb_init();
- DEBUG_INIT(NULL, 0);
-
- printf("Connecting to cluster (%s)\n", connect_string);
-
- Ndb_cluster_connection * conn = connect(connect_string);
- Ndb *db = new Ndb(conn);
- db->init(4);
-
- TableSpec spec("ndbmemcache.demo_table", "mkey", "string_value");
- spec.cas_column = "cas_value";
- spec.math_column = "math_value";
- QueryPlan plan(db, &spec);
-
+ int optc;
+ int req_level;
int npass = 0, nfail = 0;
+ Ndb_cluster_connection * conn = NULL;
+ QueryPlan *plan = NULL;
+ Ndb *db = NULL;
+
+ /* Options */
+ while((optc = getopt(argc, argv, "hlc:t:")) != -1) {
+ switch(optc) {
+ case 'c':
+ connect_string = optarg;
+ break;
+ case 't':
+ test_number = atoi(optarg);
+ if(test_number > 0) test_number -= 1;
+ else test_name = optarg;
+ break;
+ case 'l':
+ return list_tests();
+ break;
+ case 'h':
+ default:
+ return usage(argv[0]);
+ break;
+ }
+ }
+
+ /* If a test name was given, find it by number */
if(test_name) {
for(int i = 0; all_tests[i].name; i++) {
if(! strcmp(test_name, all_tests[i].name)) {
@@ -77,24 +87,80 @@ int main(int argc, char *argv[]) {
exit(1);
}
}
+
+ /* Determine requirements level for this test */
+ if(test_number >= 0)
+ req_level = all_tests[test_number].requires;
+ else
+ req_level = REQ_DEMO_TABLE; // highest level
+
+ ndb_init();
+ DEBUG_INIT(NULL, 0);
+
+ if(req_level >= REQ_NDB_CONNECTION) {
+ printf("Connecting to cluster (%s)\n", connect_string);
+ conn = connect(connect_string);
+ db = new Ndb(conn);
+ db->init(4);
+ }
+
+ if(req_level >= REQ_DEMO_TABLE) {
+ TableSpec spec("ndbmemcache.demo_table", "mkey", "string_value");
+ spec.cas_column = "cas_value";
+ spec.math_column = "math_value";
+ plan = new QueryPlan(db, &spec);
+ }
- if(test_number > -1) {
+ if(test_number >= 0) { /* Run a particular test */
printf("%s\n", all_tests[test_number].name);
- int r = all_tests[test_number].function(& plan, 1); //verbose
- printf(" %s\n", r ? "[PASS]" : "[FAIL]");
- if(r) npass++;
- else nfail++;
+ int r = all_tests[test_number].function(plan, 1); //verbose
+ if(r) {
+ printf(" [FAIL] at line %d\n", r); nfail++;
+ } else {
+ printf(" [PASS]\n"); npass++;
+ }
}
- else {
+ else { /* Run all tests */
for(int i = 0; all_tests[i].name; i++) {
- printf("%-30s", all_tests[i].name);
- int r = all_tests[i].function(& plan, 0); // quiet
- printf(" %s\n", r ? "[PASS]" : "[FAIL]");
- if(r) npass++;
- else nfail++;
+ if(all_tests[i].enabled) {
+ printf("%-30s", all_tests[i].name);
+ int r = all_tests[i].function(plan, 0); // quiet
+ printf(" %s\n", r ? "[FAIL]" : "[PASS]");
+ if(r) nfail++;
+ else npass++;
+ }
}
- printf("\nTotals: %d pass ... %d fail\n", npass, nfail);
+ printf("\nTotals: %d pass ... %d fail\n", npass, nfail);
}
+
+ exit((nfail > 0));
+}
+
+
+int list_tests() {
+ printf("\n");
+ printf("No. %-30s %-20s %-10s\n", "Name", "Requires","Enabled");
+ printf("----------------------------------------------------------------\n");
+ for(int i = 0; all_tests[i].name; i++)
+ printf("%d %-30s %-20s %-10s\n", i+1, all_tests[i].name,
+ requirements[all_tests[i].requires],
+ all_tests[i].enabled ? "Yes" : "No");
+ printf("\n");
+ return 0;
+}
+
+
+int usage(char *prog) {
+ printf("\n");
+ printf("usage %s [options]\n", prog);
+ printf("options: \n");
+ printf(" -c connectstring : specify NDB connect-string\n");
+ printf(" -t test-id : run a particular test by number or name\n");
+ printf(" -l : list tests\n");
+ printf(" -h : help\n");
+ printf("\n");
+
+ return 0;
}
=== added file 'storage/ndb/memcache/unit/tsv.cc'
--- a/storage/ndb/memcache/unit/tsv.cc 1970-01-01 00:00:00 +0000
+++ b/storage/ndb/memcache/unit/tsv.cc 2011-05-16 06:14:51 +0000
@@ -0,0 +1,157 @@
+/*
+ Copyright (c) 2011, 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 the Free Software Foundation; version 2 of
+ the License.
+
+ 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., 51 Franklin St, Fifth Floor, Boston, MA
+ 02110-1301 USA
+ */
+#include <stdio.h>
+#include <assert.h>
+
+#include "TabSeparatedValues.h"
+
+#include "all_tests.h"
+
+
+int run_tsv_test(QueryPlan *, int v) {
+ {
+ TabSeparatedValues t1("frodo.xxx", 4, 5);
+ require(t1.getLength() == 5);
+ require(t1.advance() == 0);
+ detail(v, "tsv test 1 OK\n");
+ }
+
+ {
+ char sam[16];
+
+ const char *v2 = "sam\tjessie"; // null-terminated
+ TabSeparatedValues t2(v2, 4, strlen(v2));
+ strncpy(sam, t2.getPointer(), t2.getLength());
+ require(! strcmp(sam, "sam"));
+ require(t2.getLength() == 3);
+
+ require( t2.advance() == 1);
+
+ require(* t2.getPointer() == 'j');
+ require(t2.getLength() == 6);
+ detail(v, "tsv test 2 OK\n");
+ }
+
+ {
+ char jes[16];
+ const char *v3 = "sam\tjessie......"; // no null terminator
+ TabSeparatedValues t3(v3, 4, 10);
+
+ require(t3.advance() == 1);
+ require(t3.getLength() == 6);
+ strncpy(jes, t3.getPointer(), t3.getLength());
+ require(strncmp(jes,"jessie", t3.getLength()) == 0);
+ detail(v, "tsv test 3 OK\n");
+ }
+
+ {
+ const char *v4 = "\tabc"; // 2 values
+ TabSeparatedValues t4(v4, 4, strlen(v4));
+
+ /* First value is null */
+ require(t4.getLength() == 0);
+
+ /* Second value */
+ require(t4.advance() == 1);
+ require(* t4.getPointer() == 'a');
+ require( t4.getLength() == 3);
+
+ /* No more */
+ require(t4.advance() == 0);
+ detail(v, "tsv test 4 OK\n");
+ }
+
+ {
+ const char *v5 = "\t\tabc"; // 3 values
+ TabSeparatedValues t5(v5, 4, strlen(v5));
+
+ /* First value is null */
+ require(t5.getLength() == 0);
+
+ /* Second value */
+ require(t5.advance() == 1);
+ require(t5.getLength() == 0);
+
+ /* Third value */
+ require(t5.advance() == 1);
+ require(* t5.getPointer() == 'a');
+ require( t5.getLength() == 3);
+
+ /* No more */
+ require(t5.advance() == 0);
+ detail(v, "tsv test 5 OK\n");
+ }
+
+ {
+ const char *v6 = "\t\tabc\t\t"; // 5 values with null terminator
+ TabSeparatedValues t6(v6, 6, strlen(v6));
+
+ /* First value is null */
+ require(t6.getLength() == 0);
+
+ /* Second value is null */
+ require(t6.advance() == 1);
+ require(t6.getLength() == 0);
+
+ /* Third value is abc */
+ require(t6.advance() == 1);
+ require( t6.getLength() == 3);
+
+ /* 4th value is null */
+ require(t6.advance() == 1);
+ require(t6.getLength() == 0);
+
+ /* 5th value is null */
+ require(t6.advance() == 1);
+ require(t6.getLength() == 0);
+
+ /* No more */
+ require(t6.advance() == 0);
+ detail(v, "tsv test 6 OK\n");
+ }
+
+ {
+ const char *v7 = "\t\tabc\t__"; // 4 values, no null
+ TabSeparatedValues t7(v7, 4, strlen(v7) - 2);
+
+ /* First value is null */
+ require(t7.getLength() == 0);
+
+ /* Second value is null */
+ require(t7.advance() == 1);
+ require(t7.getLength() == 0);
+
+ /* Third value is abc */
+ require(t7.advance() == 1);
+ require(t7.getLength() == 3);
+
+ /* 4th value is null */
+ require(t7.advance() == 1);
+ require(t7.getLength() == 0);
+
+ /* No more */
+ require(t7.advance() == 0);
+ detail(v, "tsv test 7 OK\n");
+ }
+
+
+ pass;
+}
+
No bundle (reason: useless for push emails).
| Thread |
|---|
| • bzr push into mysql-5.1-telco-7.2 branch (john.duncan:4171 to 4176) | John David Duncan | 16 May |