List:Commits« Previous MessageNext Message »
From:John David Duncan Date:May 16 2011 5:02pm
Subject:bzr push into mysql-5.1-telco-7.2 branch (john.duncan:4171 to 4176)
View as plain text  
 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 Duncan16 May