List:Commits« Previous MessageNext Message »
From:John David Duncan Date:November 7 2011 10:02pm
Subject:bzr push into mysql-5.5-cluster branch (john.duncan:3633 to 3634)
View as plain text  
 3634 John David Duncan	2011-11-07 [merge]
      merge from local working branch

    added:
      mysql-test/suite/ndb_memcache/r/unique_idx.result
      mysql-test/suite/ndb_memcache/t/unique_idx.test
    modified:
      storage/ndb/memcache/include/KeyPrefix.h
      storage/ndb/memcache/include/QueryPlan.h
      storage/ndb/memcache/include/workitem.h
      storage/ndb/memcache/scripts/pmpstack.awk
      storage/ndb/memcache/src/QueryPlan.cc
      storage/ndb/memcache/src/ndb_worker.cc
 3633 John David Duncan	2011-11-07 [merge]
      merge from local working branch

    modified:
      storage/ndb/memcache/include/int3korr.h
=== added file 'mysql-test/suite/ndb_memcache/r/unique_idx.result'
--- a/mysql-test/suite/ndb_memcache/r/unique_idx.result	1970-01-01 00:00:00 +0000
+++ b/mysql-test/suite/ndb_memcache/r/unique_idx.result	2011-11-07 21:54:07 +0000
@@ -0,0 +1,7 @@
+SELECT * FROM ndbmemcache.test_unique_idx;
+pkey	mkey	val
+1	key1	Quotidien
+2	key2	Passable
+3	key3	Assez bien
+4	key4	Pas trop mal...
+DELETE   FROM ndbmemcache.test_unique_idx;

=== added file 'mysql-test/suite/ndb_memcache/t/unique_idx.test'
--- a/mysql-test/suite/ndb_memcache/t/unique_idx.test	1970-01-01 00:00:00 +0000
+++ b/mysql-test/suite/ndb_memcache/t/unique_idx.test	2011-11-07 21:54:07 +0000
@@ -0,0 +1,115 @@
+################################################################
+# Test access via unique index 
+#
+# Write-access via unique index is subject to some restrictions:
+#
+# (1) Inserts are not allowed; they will fail with NOT_FOUND
+# (2) Updates that do not contain the PK column are allowed
+# (3) Updates that contain the PK column are allowed if the PK value 
+#     does not change, but attempts to change the PK fail with NOT_STORED.
+
+
+--source suite/ndb_memcache/include/have_memcache.inc
+--source suite/ndb_memcache/include/memcached_wait_for_ready.inc
+
+
+# 
+# Configuration change for this test
+#
+
+--disable_query_log
+--disable_result_log
+USE ndbmemcache;
+CREATE TABLE test_unique_idx (pkey int PRIMARY KEY, 
+                              mkey char(40), 
+                              val varchar(200),
+                              UNIQUE INDEX (mkey)
+                              ) ENGINE=ndbcluster;
+
+INSERT INTO containers (name, db_schema, db_table, key_columns, value_columns)
+  VALUES("tt_uidx_pk", "ndbmemcache", "test_unique_idx", "pkey", "mkey,val"),
+        ("tt_uidx_rd", "ndbmemcache", "test_unique_idx", "mkey", "pkey,val"),
+        ("tt_uidx_uk", "ndbmemcache", "test_unique_idx", "mkey", "val");
+
+INSERT INTO key_prefixes(server_role_id, key_prefix, policy, container) 
+  VALUES(0, "tup:", "ndb-only", "tt_uidx_pk"),
+        (0, "tur:", "ndb-only", "tt_uidx_rd"),
+        (0, "tui:", "ndb-only", "tt_uidx_uk");
+
+UPDATE memcache_server_roles set update_timestamp = NOW() where role_id = 0;
+--enable_query_log
+--enable_result_log
+
+# 
+#  Memcache operations for this test
+#
+
+--perl
+
+use strict;
+use Carp;
+use lib "lib";
+use My::Memcache;
+my $mc = My::Memcache->new();  
+my $port = $ENV{MTR_BUILD_THREAD} * 10 + 10000 + 8;
+my $r = $mc->connect("localhost",$port);
+
+my $cf_gen = $mc->wait_for_reconf();
+
+if($cf_gen == 0) {
+  Carp::confess("FAILED WAIT_FOR_RECONF");
+}
+
+# 1: SET on primary key
+$mc->set("tup:1","key1\tSuperbe!")        || Carp::confess("Failed test 1.A");
+$mc->set("tup:2","key2\tIncroyable!")     || Carp::confess("Failed test 1.B");
+$mc->set("tup:3","key3\tTres bien fait");
+$mc->set("tup:4","key4\tPas mal");
+
+# 2: GET on primary key
+($mc->get("tup:1") == "key1\tSuperbe!")   || Carp::confess("Failed test 2.A");
+($mc->get("tup:2") == "key2\tIncroyable!")|| Carp::confess("Failed test 2.B");
+
+# 3: GET via unique key (two value columns)
+($mc->get("tur:key1") == "1\tSuperbe!")   || Carp::confess("Failed test 3.");
+
+# 4: GET via unique key (one value column)
+($mc->get("tui:key2") == "Incroyable!")   || Carp::confess("Failed test 4.");
+
+# 5. SET via unique key (one value column, not part of primary key)
+$mc->set("tui:key3", "Assez bien")        || Carp::confess("Failed test 5.A");
+$mc->set("tui:key4", "Pas trop mal...")   || Carp::confess("Failed test 5.B");
+
+# 6. REPLACE via unique key (one value column, not part of primary key)
+$mc->replace("tui:key2", "Passable")  || Carp::confess("Failed test 6");
+
+# 7. Inserts via unique key access fail with NOT_FOUND:
+# (A) SET
+($mc->set("tui:key5", "rien") == 0)   || Carp::confess("Test 7.A SET should fail");
+($mc->{error} =~ "NOT_FOUND")         || Carp::confess("Test 7.A expected NOT_FOUND");
+
+# (B) ADD
+($mc->add("tui:key6", "rien") == 0)   || Carp::confess("Test 7.B ADD should fail");
+($mc->{error} =~ "NOT_FOUND")         || Carp::confess("Test 7.B expected NOT_FOUND");
+
+# 8. Update via unique key succeeds if PK is equal to old PK
+$mc->set("tur:key1", "1\tQuotidien")  || Carp::confess("Failed test 8.A");
+($mc->get("tui:key1") == "Quotidien") || Carp::confess("Failed test 8.B");
+
+# 9. Attempt to change PK fails with NOT_STORED
+($mc->set("tur:key3", "5\tJamais!") == 0) || Carp::confess("Test 9 SET should fail.");
+($mc->{error} =~ "NOT_STORED")         || Carp::confess("Test 9 expected NOT_STORED");
+
+EOF
+
+# At the end of the test the values should be
+# 1 Quotidien
+# 2 Passable 
+# 3 Assez bien
+# 4 Pas trop mal...
+
+
+--sorted_result
+SELECT * FROM ndbmemcache.test_unique_idx;
+DELETE   FROM ndbmemcache.test_unique_idx;
+

=== modified file 'storage/ndb/memcache/include/KeyPrefix.h'
--- a/storage/ndb/memcache/include/KeyPrefix.h	2011-09-12 10:05:07 +0000
+++ b/storage/ndb/memcache/include/KeyPrefix.h	2011-11-07 21:54:07 +0000
@@ -22,7 +22,7 @@
 
 #include <stdio.h>
 
-/***** This section defines a data structures available to C. ***/
+/***** This section defines data structures available to C. ***/
 /* The prefix_info_t is the compacted form of the parts of the 
    KeyPrefix that must be available to C code. 
 */

=== modified file 'storage/ndb/memcache/include/QueryPlan.h'
--- a/storage/ndb/memcache/include/QueryPlan.h	2011-09-30 16:22:30 +0000
+++ b/storage/ndb/memcache/include/QueryPlan.h	2011-11-07 21:54:07 +0000
@@ -47,16 +47,16 @@ class QueryPlan {
   QueryPlan() : initialized(0)  {};  
   QueryPlan(Ndb *, const TableSpec *, PlanOpts opts = NoOptions); 
   ~QueryPlan();
-  bool keyIsPrimaryKey() const;
   void debug_dump() const;
    
   /* public instance variables */
   bool initialized;
-  bool dup_numbers;
+  bool dup_numbers;                /* dup_numbers mode for ascii incr/decr */
+  bool pk_access;                  /* access by primary key */
+  bool is_scan;
   const TableSpec *spec;
   NdbDictionary::Dictionary *dict;
   const NdbDictionary::Table *table;
-  bool is_scan;
   short cas_column_id;
   short math_column_id;
   unsigned int static_flags;
@@ -74,6 +74,7 @@ class QueryPlan {
   private:
   /* Private methods */
   const NdbDictionary::Index * chooseIndex();
+  bool keyIsPrimaryKey() const;
 
   /* Private instance variables */
   Ndb *db;

=== modified file 'storage/ndb/memcache/include/workitem.h'
--- a/storage/ndb/memcache/include/workitem.h	2011-10-01 01:01:07 +0000
+++ b/storage/ndb/memcache/include/workitem.h	2011-11-07 21:54:07 +0000
@@ -45,11 +45,11 @@ typedef struct workitem {
     unsigned verb        : 4;  /*! READ, DELETE, ADD, STORE, etc. */
     unsigned math_incr   : 1;  /*! incr, or decr ? */
     unsigned math_create : 1;  /*! create record if not existing */
-    unsigned _unused_1   : 1;  /*! (formerly was is_sync) */
+    unsigned _unused_1   : 1;  /*! */
     unsigned has_value   : 1;  /*! are we able to use a no-copy value? */
     unsigned retries     : 3;  /*! how many times this job has been retried */
     unsigned complete    : 1;  /*! is this operation finished? */
-    unsigned broker      : 2;  /*! for use by the flex scheduler */
+    unsigned _unused_2   : 2;  /*! */
     unsigned reschedule  : 1;  /*! inform scheduler to send and poll again */
     unsigned cas_owner   : 1;  /*! set if this engine owns the CAS ID */
   } base;

=== modified file 'storage/ndb/memcache/scripts/pmpstack.awk'
--- a/storage/ndb/memcache/scripts/pmpstack.awk	2011-09-12 10:05:07 +0000
+++ b/storage/ndb/memcache/scripts/pmpstack.awk	2011-11-07 21:54:07 +0000
@@ -23,7 +23,6 @@
 function label(name)  {
    if(thr == "event") event[name] += $1;
    else if(thr == "commit") commit[name] += $1;
-   else if(thr == "broker") broker[name] += $1;
    else if(thr == "send")   send[name]   += $1;
    else if(thr == "poll")   poll[name]   += $1;
 }   
@@ -33,9 +32,7 @@ function label(name)  {
                                        { thr="x" }   # undetermined
 
 /event_base_loop,worker_libevent/      { event["total"]  += $1; thr="event" } 
-/run_commit_thread/                    { commit["total"] += $1; thr="commit" }
 /run_ndb_commit_thread/                { commit["total"] += $1; thr="commit" }
-/run_broker_thread/                    { broker["total"] += $1; thr="broker" }
 /run_ndb_send_thread/                  { send["total"] += $1  ; thr="send"   }
 /run_ndb_poll_thread/                  { poll["total"] += $1  ; thr="poll"   }
 
@@ -81,11 +78,6 @@ END { 
               "Event", (event[i] / event["total"]) * 100, i)
       printf("\n");
 
-      for(i in broker) if (i != "total")
-       printf("%s\t%.2f%%\t%s\n", 
-              "Broker", (broker[i] / broker["total"]) * 100, i)
-      if(broker["total"]) printf("\n");
-
       for(i in commit) if(i != "total")
        printf("%s\t%.2f%%\t%s\n", 
               "Commit", (commit[i] / commit["total"]) * 100, i)

=== modified file 'storage/ndb/memcache/src/QueryPlan.cc'
--- a/storage/ndb/memcache/src/QueryPlan.cc	2011-10-14 08:26:28 +0000
+++ b/storage/ndb/memcache/src/QueryPlan.cc	2011-11-07 21:54:07 +0000
@@ -125,8 +125,11 @@ QueryPlan::QueryPlan(Ndb *my_ndb, const 
     math_mask_i[this_col_id >> 3] |= (1 << (this_col_id & 7));
   }
 
+  /* Primary Key access path? */
+  pk_access = keyIsPrimaryKey();
+
   /* Choose an access path and complete the key record*/
-  if(keyIsPrimaryKey() && ! (opts == PKScan)) {
+  if(pk_access && ! (opts == PKScan)) {
     op_ok = key_record->complete(dict, table);
   }
   else {
@@ -232,6 +235,7 @@ void QueryPlan::debug_dump() const {
   }
 }
 
+
 bool QueryPlan::keyIsPrimaryKey() const {
   if(spec->nkeycols == table->getNoOfPrimaryKeys()) {
     for(int i = 0 ; i < spec->nkeycols ; i++) 

=== modified file 'storage/ndb/memcache/src/ndb_worker.cc'
--- a/storage/ndb/memcache/src/ndb_worker.cc	2011-10-07 20:38:22 +0000
+++ b/storage/ndb/memcache/src/ndb_worker.cc	2011-11-07 21:54:07 +0000
@@ -103,6 +103,9 @@ status_block status_block_bad_add = 
 status_block status_block_bad_replace =
   { ENGINE_NOT_STORED, "Tuple not found"              };
   
+status_block status_block_idx_insert = 
+  { ENGINE_NOT_STORED, "Cannot insert via unique index" };
+  
 
 void worker_set_cas(ndb_pipeline *p, uint64_t *cas) {  
   /* Be careful here --  ndbmc_atomic32_t might be a signed type.
@@ -350,23 +353,33 @@ op_status_t worker_do_read(workitem *wqi
   NdbTransaction *tx = op.startTransaction(wqitem->ndb_instance->db);
   DEBUG_ASSERT(tx);
 
-  if(! op.readTuple(tx)) {
+  bool op_is_read_before_write;
+  ndb_async_callback *next_op;
+  
+  if (wqitem->base.verb == OPERATION_APPEND || wqitem->base.verb == OPERATION_PREPEND) {
+    op_is_read_before_write = true;
+    next_op = rewrite_callback;
+  }
+  else {
+    op_is_read_before_write = false;
+    next_op = DB_callback;
+  }
+
+  /* Simple primary key reads use a SimpleRead lock.  
+     Unique index reads need a Read lock. 
+     APPEND and PREPEND need an Exclusive lock. */
+  NdbOperation::LockMode lockmode = NdbOperation::LM_SimpleRead;
+  if(op_is_read_before_write) lockmode = NdbOperation::LM_Exclusive;
+  else if(! plan->pk_access)  lockmode = NdbOperation::LM_Read;
+  
+  if(! op.readTuple(tx, lockmode)) {
     logger->log(LOG_WARNING, 0, "readTuple(): %s\n", tx->getNdbError().message);
     tx->close();
     return op_failed;
   }
 
   /* Save the workitem in the transaction and prepare for async execution */   
-  if(wqitem->base.verb == OPERATION_APPEND || wqitem->base.verb == OPERATION_PREPEND) 
-  {
-    DEBUG_PRINT("In read() portion of APPEND.  Value = %s", 
-                hash_item_get_data(wqitem->cache_item));
-    tx->executeAsynchPrepare(NdbTransaction::NoCommit, rewrite_callback, (void *) wqitem);
-  }
-  else 
-  {
-    tx->executeAsynchPrepare(NdbTransaction::Commit, DB_callback, (void *) wqitem);
-  }
+  tx->executeAsynchPrepare(NdbTransaction::NoCommit, next_op, (void *) wqitem);
 
   return op_async_prepared;
 }
@@ -551,6 +564,10 @@ void DB_callback(int result, NdbTransact
     if(wqitem->cas) * wqitem->cas = 0ULL;
     return_status = & status_block_bad_add;    
   }
+  /* Attempt to insert via unique index access */
+  else if(tx->getNdbError().code == 897) {
+    return_status = & status_block_idx_insert;
+  }
   /* Some other error */
   else  {
     DEBUG_PRINT("[%d]: %s", 
@@ -916,7 +933,7 @@ ENGINE_ERROR_CODE ndb_flush_all(ndb_pipe
       Ndb_cluster_connection *conn = pool->getMainConnection();
       NdbInstance inst(conn, 128);
       QueryPlan plan(inst.db, pfx->table);
-      if(plan.keyIsPrimaryKey()) {
+      if(plan.pk_access) {
         // To flush, scan the table and delete every row
         DEBUG_PRINT("prefix %d - deleting from %s", i, pfx->table->table_name);
         scan_delete(&inst, &plan);

No bundle (reason: useless for push emails).
Thread
bzr push into mysql-5.5-cluster branch (john.duncan:3633 to 3634) John David Duncan9 Nov