List:Commits« Previous MessageNext Message »
From:jonas Date:March 19 2008 12:57pm
Subject:bk commit into 5.1 tree (jonas:1.2561) BUG#35208
View as plain text  
Below is the list of changes that have just been committed into a local
5.1 repository of jonas.  When jonas does a push these changes
will be propagated to the main repository and, within 24 hours after the
push, to the public repository.
For information on how to access the public repository
see http://dev.mysql.com/doc/mysql/en/installing-source-tree.html

ChangeSet@stripped, 2008-03-19 13:57:01+01:00, jonas@stripped +14 -0
  ndb - bug#35208
    remove "common-case" 64 bit changemask
    and replace by general anybit-changemask

  mysql-test/suite/rpl_ndb/r/rpl_ndb_basic.result@stripped, 2008-03-19 13:56:57+01:00, jonas@stripped +20 -0
    new testcase

  mysql-test/suite/rpl_ndb/t/rpl_ndb_basic.test@stripped, 2008-03-19 13:56:57+01:00, jonas@stripped +29 -0
    new testcase

  storage/ndb/src/kernel/blocks/dbtup/Dbtup.hpp@stripped, 2008-03-19 13:56:57+01:00, jonas@stripped +68 -60
    remove changemask state (and value from op-rec)
    and put it on copy-tuple instead

  storage/ndb/src/kernel/blocks/dbtup/DbtupAbort.cpp@stripped, 2008-03-19 13:56:57+01:00, jonas@stripped +2 -2
    remove changemask state (and value from op-rec)
    and put it on copy-tuple instead

  storage/ndb/src/kernel/blocks/dbtup/DbtupCommit.cpp@stripped, 2008-03-19 13:56:57+01:00, jonas@stripped +20 -56
    remove changemask state (and value from op-rec)
    and put it on copy-tuple instead

  storage/ndb/src/kernel/blocks/dbtup/DbtupExecQuery.cpp@stripped, 2008-03-19 13:56:57+01:00, jonas@stripped +33 -31
    remove changemask state (and value from op-rec)
    and put it on copy-tuple instead

  storage/ndb/src/kernel/blocks/dbtup/DbtupIndex.cpp@stripped, 2008-03-19 13:56:57+01:00, jonas@stripped +4 -4
    remove changemask state (and value from op-rec)
    and put it on copy-tuple instead

  storage/ndb/src/kernel/blocks/dbtup/DbtupMeta.cpp@stripped, 2008-03-19 13:56:57+01:00, jonas@stripped +4 -0
    remove changemask state (and value from op-rec)
    and put it on copy-tuple instead

  storage/ndb/src/kernel/blocks/dbtup/DbtupRoutines.cpp@stripped, 2008-03-19 13:56:57+01:00, jonas@stripped +0 -7
    remove changemask state (and value from op-rec)
    and put it on copy-tuple instead

  storage/ndb/src/kernel/blocks/dbtup/DbtupTrigger.cpp@stripped, 2008-03-19 13:56:57+01:00, jonas@stripped +8 -8
    remove changemask state (and value from op-rec)
    and put it on copy-tuple instead

  storage/ndb/src/kernel/blocks/dbtup/Undo_buffer.cpp@stripped, 2008-03-19 13:56:57+01:00, jonas@stripped +1 -1
    remove changemask state (and value from op-rec)
    and put it on copy-tuple instead

  storage/ndb/src/kernel/blocks/dbtup/Undo_buffer.hpp@stripped, 2008-03-19 13:56:57+01:00, jonas@stripped +1 -1
    remove changemask state (and value from op-rec)
    and put it on copy-tuple instead

  storage/ndb/test/ndbapi/test_event.cpp@stripped, 2008-03-19 13:56:57+01:00, jonas@stripped +173 -0
    new testcase

  storage/ndb/test/run-test/daily-basic-tests.txt@stripped, 2008-03-19 13:56:57+01:00, jonas@stripped +4 -0
    new testcase

diff -Nrup a/mysql-test/suite/rpl_ndb/r/rpl_ndb_basic.result b/mysql-test/suite/rpl_ndb/r/rpl_ndb_basic.result
--- a/mysql-test/suite/rpl_ndb/r/rpl_ndb_basic.result	2007-11-28 11:54:27 +01:00
+++ b/mysql-test/suite/rpl_ndb/r/rpl_ndb_basic.result	2008-03-19 13:56:57 +01:00
@@ -248,3 +248,23 @@ c1
 104
 105
 DROP TABLE t1;
+create table t1 (a int primary key,
+b00 int,b01 int,b02 int,b03 int,b04 int,b05 int,b06 int,b07 int,
+b08 int,b09 int,b10 int,b11 int,b12 int,b13 int,b14 int,b15 int,
+b16 int,b17 int,b18 int,b19 int,b20 int,b21 int,b22 int,b23 int,
+b24 int,b25 int,b26 int,b27 int,b28 int,b29 int,b30 int,b31 int,
+b32 int,b33 int,b34 int,b35 int,b36 int,b37 int,b38 int,b39 int,
+b40 int,b41 int,b42 int,b43 int,b44 int,b45 int,b46 int,b47 int,
+b48 int,b49 int,b50 int,b51 int,b52 int,b53 int,b54 int,b55 int,
+b56 int,b57 int,b58 int,b59 int,b60 int,b61 int,b62 int,b63 int,
+b64 int,b65 int,b66 int,b67 int,b68 int,b69 int,b70 int) engine=ndb;
+insert into t1 (a,b00) values (1,1);
+update t1 set b00 = 2 where a = 1;
+update t1 set b66 = 1 where a = 1;
+select b00 from t1;
+b00
+1
+select b00 from t1;
+b00
+2
+DROP TABLE t1;
diff -Nrup a/mysql-test/suite/rpl_ndb/t/rpl_ndb_basic.test b/mysql-test/suite/rpl_ndb/t/rpl_ndb_basic.test
--- a/mysql-test/suite/rpl_ndb/t/rpl_ndb_basic.test	2007-09-06 06:45:47 +02:00
+++ b/mysql-test/suite/rpl_ndb/t/rpl_ndb_basic.test	2008-03-19 13:56:57 +01:00
@@ -267,4 +267,33 @@ SELECT c1 FROM t1 ORDER BY c1 LIMIT 5;
 # cleanup
 --connection master
 DROP TABLE t1;
+
+# bug#35208
+# NOTE: should use ndb_log_updated_only
+create table t1 (a int primary key,
+b00 int,b01 int,b02 int,b03 int,b04 int,b05 int,b06 int,b07 int,
+b08 int,b09 int,b10 int,b11 int,b12 int,b13 int,b14 int,b15 int,
+b16 int,b17 int,b18 int,b19 int,b20 int,b21 int,b22 int,b23 int,
+b24 int,b25 int,b26 int,b27 int,b28 int,b29 int,b30 int,b31 int,
+b32 int,b33 int,b34 int,b35 int,b36 int,b37 int,b38 int,b39 int,
+b40 int,b41 int,b42 int,b43 int,b44 int,b45 int,b46 int,b47 int,
+b48 int,b49 int,b50 int,b51 int,b52 int,b53 int,b54 int,b55 int,
+b56 int,b57 int,b58 int,b59 int,b60 int,b61 int,b62 int,b63 int,
+b64 int,b65 int,b66 int,b67 int,b68 int,b69 int,b70 int) engine=ndb;
+
+insert into t1 (a,b00) values (1,1);
+--sync_slave_with_master
+--connection slave
+update t1 set b00 = 2 where a = 1;
+--connection master
+update t1 set b66 = 1 where a = 1;
+--sync_slave_with_master
+# after bug fix result *should* be different on master/slave
+--connection master
+select b00 from t1;
+--connection slave
+select b00 from t1;
+
+DROP TABLE t1;
+
 -- source include/master-slave-end.inc
diff -Nrup a/storage/ndb/src/kernel/blocks/dbtup/Dbtup.hpp b/storage/ndb/src/kernel/blocks/dbtup/Dbtup.hpp
--- a/storage/ndb/src/kernel/blocks/dbtup/Dbtup.hpp	2008-02-06 13:08:29 +01:00
+++ b/storage/ndb/src/kernel/blocks/dbtup/Dbtup.hpp	2008-03-19 13:56:57 +01:00
@@ -365,14 +365,6 @@ public:
   Lgman* c_lgman;
   Page_cache_client m_pgman;
 
-// State values
-enum ChangeMaskState {
-  DELETE_CHANGES = 0,
-  SET_ALL_MASK = 1,
-  USE_SAVED_CHANGE_MASK = 2,
-  RECALCULATE_CHANGE_MASK = 3
-};
-
 enum TransState {
   TRANS_IDLE = 0,
   TRANS_STARTED = 1,
@@ -818,11 +810,6 @@ struct Operationrec {
   };
 
   /*
-   * We use 64 bits to save change mask for the most common cases.
-   */
-  Uint32 saved_change_mask[2];
-
-  /*
    * State variables on connection.
    * State variable on tuple after multi-updates
    * Is operation undo logged or not
@@ -840,7 +827,7 @@ struct Operationrec {
     unsigned int op_type : 3;
     unsigned int delete_insert_flag : 1;
     unsigned int primary_replica : 1;
-    unsigned int change_mask_state : 2;
+    unsigned int unused : 2;
     unsigned int m_disk_preallocated : 1;
     unsigned int m_load_diskpage_on_commit : 1;
     unsigned int m_wait_log_buffer : 1;
@@ -1586,11 +1573,9 @@ struct KeyReqStruct {
   Uint32 trans_id2;
   Uint32 TC_index;
   // next 2 apply only to attrids >= 64 (zero otherwise)
-  Uint32 max_attr_id_updated;
-  Uint32 no_changed_attrs;
   BlockReference TC_ref;
   BlockReference rec_blockref;
-  bool change_mask_calculated;
+
   /*
    * A bit mask where a bit set means that the update or insert
    * was updating this record.
@@ -2437,10 +2422,13 @@ private:
   Uint32 get_fix_page_offset(Uint32 page_index, Uint32 tuple_size);
 
   Uint32 decr_tup_version(Uint32 tuple_version);
-  void set_change_mask_state(Operationrec * const, ChangeMaskState);
-  ChangeMaskState get_change_mask_state(Operationrec * const);
-  void update_change_mask_info(KeyReqStruct * const, Operationrec * const);
-  void set_change_mask_info(KeyReqStruct * const, Operationrec * const);
+  void update_change_mask_info(const Tablerec*, Uint32* dst, const Uint32*src);
+  void set_change_mask_info(const Tablerec*, Uint32* dst);
+  void clear_change_mask_info(const Tablerec*, Uint32* dst);
+  void copy_change_mask_info(const Tablerec*, Uint32* dst, const Uint32* src);
+  void set_commit_change_mask_info(const Tablerec*,
+                                   KeyReqStruct*,
+                                   const Operationrec*);
 
 //------------------------------------------------------------------
 //------------------------------------------------------------------
@@ -2738,10 +2726,6 @@ private:
   void findBeforeValueOperation(OperationrecPtr& befOpPtr,
                                 OperationrecPtr firstOpPtr);
 
-  void calculateChangeMask(Page* PagePtr,
-                           Tablerec* regTabPtr,
-                           KeyReqStruct * req_struct);
-
   void updateGcpId(KeyReqStruct *req_struct,
                    Operationrec* regOperPtr,
                    Fragrecord* regFragPtr,
@@ -3060,6 +3044,25 @@ private:
   Uint32* get_dd_ptr(PagePtr*, const Local_key*, const Tablerec*);
   Uint32 get_len(Ptr<Page>* pagePtr, Var_part_ref ref);
 
+  Tuple_header* alloc_copy_tuple(const Tablerec* tabPtrP, Local_key* ptr){
+    Uint32 * dst = c_undo_buffer.alloc_copy_tuple(ptr, tabPtrP->total_rec_size);
+    if (unlikely(dst == 0))
+      return 0;
+    dst += ((tabPtrP->m_no_of_attributes + 31) >> 5);
+    return (Tuple_header*)dst;
+  }
+
+  Tuple_header* get_copy_tuple(const Tablerec* tabPtrP, const Local_key* ptr){
+    Uint32 mask = (tabPtrP->m_no_of_attributes + 31) >> 5;
+    return (Tuple_header*)(c_undo_buffer.get_ptr(ptr) + mask);
+  }
+
+  Uint32* get_change_mask_ptr(const Tablerec* tabP, Tuple_header* copy_tuple){
+    Uint32 * tmp = (Uint32*)copy_tuple;
+    tmp -= ((tabP->m_no_of_attributes + 31) >> 5);
+    return tmp;
+  }
+
   /**
    * prealloc space from disk
    *   key.m_file_no  contains file no
@@ -3236,41 +3239,6 @@ Dbtup::decr_tup_version(Uint32 tup_versi
 }
 
 inline
-Dbtup::ChangeMaskState
-Dbtup::get_change_mask_state(Operationrec * regOperPtr)
-{
-  return (Dbtup::ChangeMaskState)regOperPtr->op_struct.change_mask_state;
-}
-
-inline
-void
-Dbtup::set_change_mask_state(Operationrec * regOperPtr,
-                             ChangeMaskState new_state)
-{
-  regOperPtr->op_struct.change_mask_state= (Uint32)new_state;
-}
-
-inline
-void
-Dbtup::update_change_mask_info(KeyReqStruct * req_struct,
-                               Operationrec * regOperPtr)
-{
-  if (req_struct->max_attr_id_updated == 0) {
-    if (get_change_mask_state(regOperPtr) == USE_SAVED_CHANGE_MASK) {
-      // add new changes
-      regOperPtr->saved_change_mask[0] |= req_struct->changeMask.getWord(0);
-      regOperPtr->saved_change_mask[1] |= req_struct->changeMask.getWord(1);
-    }
-  } else {
-    if (req_struct->no_changed_attrs < 16) {
-      set_change_mask_state(regOperPtr, RECALCULATE_CHANGE_MASK);
-    } else {
-      set_change_mask_state(regOperPtr, SET_ALL_MASK);
-    }
-  }
-}
-
-inline
 Uint32*
 Dbtup::get_ptr(Var_part_ref ref)
 {
@@ -3354,6 +3322,46 @@ bool Dbtup::find_savepoint(OperationrecP
     c_operation_pool.getPtr(loopOpPtr);
   }
   return false;
+}
+
+inline
+void
+Dbtup::update_change_mask_info(const Tablerec* tablePtrP,
+                               Uint32* dst,
+                               const Uint32 * src)
+{
+  Uint32 len = (tablePtrP->m_no_of_attributes + 31) >> 5;
+  for (Uint32 i = 0; i<len; i++)
+  {
+    * dst |= *src;
+    dst++;
+    src++;
+  }
+}
+
+inline
+void
+Dbtup::set_change_mask_info(const Tablerec* tablePtrP, Uint32* dst)
+{
+  Uint32 len = (tablePtrP->m_no_of_attributes + 31) >> 5;
+  BitmaskImpl::set(len, dst);
+}
+
+inline
+void
+Dbtup::clear_change_mask_info(const Tablerec* tablePtrP, Uint32* dst)
+{
+  Uint32 len = (tablePtrP->m_no_of_attributes + 31) >> 5;
+  BitmaskImpl::clear(len, dst);
+}
+
+inline
+void
+Dbtup::copy_change_mask_info(const Tablerec* tablePtrP,
+                             Uint32* dst, const Uint32* src)
+{
+  Uint32 len = (tablePtrP->m_no_of_attributes + 31) >> 5;
+  memcpy(dst, src, 4*len);
 }
 
 #endif
diff -Nrup a/storage/ndb/src/kernel/blocks/dbtup/DbtupAbort.cpp b/storage/ndb/src/kernel/blocks/dbtup/DbtupAbort.cpp
--- a/storage/ndb/src/kernel/blocks/dbtup/DbtupAbort.cpp	2008-02-06 13:08:29 +01:00
+++ b/storage/ndb/src/kernel/blocks/dbtup/DbtupAbort.cpp	2008-03-19 13:56:57 +01:00
@@ -128,8 +128,8 @@ void Dbtup::do_tup_abortreq(Signal* sign
   Uint32 bits= tuple_ptr->m_header_bits;  
   if(regOperPtr.p->op_struct.op_type != ZDELETE)
   {
-    Tuple_header *copy= (Tuple_header*)
-      c_undo_buffer.get_ptr(&regOperPtr.p->m_copy_tuple_location);
+    Tuple_header *copy=
+      get_copy_tuple(regTabPtr.p, &regOperPtr.p->m_copy_tuple_location);
     
     if(regOperPtr.p->op_struct.m_disk_preallocated)
     {
diff -Nrup a/storage/ndb/src/kernel/blocks/dbtup/DbtupCommit.cpp b/storage/ndb/src/kernel/blocks/dbtup/DbtupCommit.cpp
--- a/storage/ndb/src/kernel/blocks/dbtup/DbtupCommit.cpp	2008-02-06 13:16:50 +01:00
+++ b/storage/ndb/src/kernel/blocks/dbtup/DbtupCommit.cpp	2008-03-19 13:56:57 +01:00
@@ -211,8 +211,8 @@ Dbtup::commit_operation(Signal* signal,
   Uint32 bits= tuple_ptr->m_header_bits;
 
   Tuple_header *disk_ptr= 0;
-  Tuple_header *copy= (Tuple_header*)
-    c_undo_buffer.get_ptr(&regOperPtr->m_copy_tuple_location);
+  Tuple_header *copy=
+    get_copy_tuple(regTabPtr, &regOperPtr->m_copy_tuple_location);
   
   Uint32 copy_bits= copy->m_header_bits;
 
@@ -576,8 +576,8 @@ void Dbtup::execTUP_COMMITREQ(Signal* si
     if(!regOperPtr.p->m_copy_tuple_location.isNull())
     {
       jam();
-      Tuple_header* tmp= (Tuple_header*)
-	c_undo_buffer.get_ptr(&regOperPtr.p->m_copy_tuple_location);
+      Tuple_header* tmp=
+        get_copy_tuple(regTabPtr.p, &regOperPtr.p->m_copy_tuple_location);
       
       memcpy(&req.m_page, 
 	     tmp->get_disk_ref_ptr(regTabPtr.p), sizeof(Local_key));
@@ -704,7 +704,7 @@ skip_disk:
      * Perform "real" commit
      */
     Uint32 disk = regOperPtr.p->m_commit_disk_callback_page;
-    set_change_mask_info(&req_struct, regOperPtr.p);
+    set_commit_change_mask_info(regTabPtr.p, &req_struct, regOperPtr.p);
     checkDetachedTriggers(&req_struct, regOperPtr.p, regTabPtr.p, 
                           disk != RNIL);
     
@@ -747,58 +747,22 @@ skip_disk:
 }
 
 void
-Dbtup::set_change_mask_info(KeyReqStruct * const req_struct,
-                            Operationrec * const regOperPtr)
+Dbtup::set_commit_change_mask_info(const Tablerec* regTabPtr,
+                                   KeyReqStruct * req_struct,
+                                   const Operationrec * regOperPtr)
 {
-  ChangeMaskState state = get_change_mask_state(regOperPtr);
-  if (state == USE_SAVED_CHANGE_MASK) {
-    jam();
-    req_struct->changeMask.setWord(0, regOperPtr->saved_change_mask[0]);
-    req_struct->changeMask.setWord(1, regOperPtr->saved_change_mask[1]);
-  } else if (state == RECALCULATE_CHANGE_MASK) {
-    jam();
-    // Recompute change mask, for now set all bits
-    req_struct->changeMask.set();
-  } else if (state == SET_ALL_MASK) {
-    jam();
-    req_struct->changeMask.set();
-  } else {
-    jam();
-    ndbrequire(state == DELETE_CHANGES);
+  Uint32 masklen = (regTabPtr->m_no_of_attributes + 31) >> 5;
+  if (regOperPtr->m_copy_tuple_location.isNull())
+  {
+    ndbassert(regOperPtr->op_struct.op_type == ZDELETE);
     req_struct->changeMask.set();
   }
-}
-
-void
-Dbtup::calculateChangeMask(Page* const pagePtr,
-                           Tablerec* const regTabPtr,
-                           KeyReqStruct * const req_struct)
-{
-  OperationrecPtr loopOpPtr;
-  Uint32 saved_word1= 0;
-  Uint32 saved_word2= 0;
-  loopOpPtr.i= req_struct->m_tuple_ptr->m_operation_ptr_i;
-  do {
-    c_operation_pool.getPtr(loopOpPtr);
-    ndbrequire(loopOpPtr.p->op_struct.op_type == ZUPDATE);
-    ChangeMaskState change_mask= get_change_mask_state(loopOpPtr.p);
-    if (change_mask == USE_SAVED_CHANGE_MASK) {
-      jam();
-      saved_word1|= loopOpPtr.p->saved_change_mask[0];
-      saved_word2|= loopOpPtr.p->saved_change_mask[1];
-    } else if (change_mask == RECALCULATE_CHANGE_MASK) {
-      jam();
-      //Recompute change mask, for now set all bits
-      req_struct->changeMask.set();
-      return;
-    } else {
-      ndbrequire(change_mask == SET_ALL_MASK);
-      jam();
-      req_struct->changeMask.set();
-      return;
-    }
-    loopOpPtr.i= loopOpPtr.p->prevActiveOp;
-  } while (loopOpPtr.i != RNIL);
-  req_struct->changeMask.setWord(0, saved_word1);
-  req_struct->changeMask.setWord(1, saved_word2);
+  else
+  {
+    Uint32 * dst = req_struct->changeMask.rep.data;
+    Tuple_header* ptr = get_copy_tuple(regTabPtr,
+                                       &regOperPtr->m_copy_tuple_location);
+    const Uint32 * maskptr = get_change_mask_ptr(regTabPtr, ptr);
+    memcpy(dst, maskptr, 4*masklen);
+  }
 }
diff -Nrup a/storage/ndb/src/kernel/blocks/dbtup/DbtupExecQuery.cpp b/storage/ndb/src/kernel/blocks/dbtup/DbtupExecQuery.cpp
--- a/storage/ndb/src/kernel/blocks/dbtup/DbtupExecQuery.cpp	2008-02-06 13:08:29 +01:00
+++ b/storage/ndb/src/kernel/blocks/dbtup/DbtupExecQuery.cpp	2008-03-19 13:56:57 +01:00
@@ -299,9 +299,6 @@ Dbtup::insertActiveOpList(OperationrecPt
   regOperPtr.p->m_undo_buffer_space= 0;
   req_struct->m_tuple_ptr->m_operation_ptr_i= regOperPtr.i;
   if (prevOpPtr.i == RNIL) {
-    set_change_mask_state(regOperPtr.p, USE_SAVED_CHANGE_MASK);
-    regOperPtr.p->saved_change_mask[0] = 0;
-    regOperPtr.p->saved_change_mask[1] = 0;
     return true;
   } else {
     req_struct->prevOpPtr.p= prevOpPtr.p= c_operation_pool.getPtr(prevOpPtr.i);
@@ -313,9 +310,6 @@ Dbtup::insertActiveOpList(OperationrecPt
       prevOpPtr.p->op_struct.m_load_diskpage_on_commit;
     regOperPtr.p->m_undo_buffer_space= prevOpPtr.p->m_undo_buffer_space;
     // start with prev mask (matters only for UPD o UPD)
-    set_change_mask_state(regOperPtr.p, get_change_mask_state(prevOpPtr.p));
-    regOperPtr.p->saved_change_mask[0] = prevOpPtr.p->saved_change_mask[0];
-    regOperPtr.p->saved_change_mask[1] = prevOpPtr.p->saved_change_mask[1];
 
     regOperPtr.p->m_any_value = prevOpPtr.p->m_any_value;
 
@@ -408,9 +402,9 @@ Dbtup::setup_read(KeyReqStruct *req_stru
     }
     else
     {
-      req_struct->m_tuple_ptr= (Tuple_header*)
-	c_undo_buffer.get_ptr(&currOpPtr.p->m_copy_tuple_location);
-    }      
+      req_struct->m_tuple_ptr=
+        get_copy_tuple(regTabPtr, &currOpPtr.p->m_copy_tuple_location);
+    }
 
     if (regTabPtr->need_expand(disk))
       prepare_read(req_struct, regTabPtr, disk);
@@ -622,8 +616,6 @@ void Dbtup::execTUPKEYREQ(Signal* signal
    req_struct.interpreted_exec= (TrequestInfo >> 10) & 1;
    req_struct.no_fired_triggers= 0;
    req_struct.read_length= 0;
-   req_struct.max_attr_id_updated= 0;
-   req_struct.no_changed_attrs= 0;
    req_struct.last_row= false;
    req_struct.changeMask.clear();
 
@@ -784,7 +776,6 @@ void Dbtup::execTUPKEYREQ(Signal* signal
 					 regOperPtr,
 					 regTabPtr,
                                          disk_page != RNIL);
-       set_change_mask_state(regOperPtr, SET_ALL_MASK);
        sendTUPKEYCONF(signal, &req_struct, regOperPtr);
        return;
      }
@@ -824,7 +815,6 @@ void Dbtup::execTUPKEYREQ(Signal* signal
 	 tupkeyErrorLab(signal);
 	 return;
        }
-       update_change_mask_info(&req_struct, regOperPtr);
        sendTUPKEYCONF(signal, &req_struct, regOperPtr);
        return;
      } 
@@ -850,7 +840,6 @@ void Dbtup::execTUPKEYREQ(Signal* signal
 					 regOperPtr, 
 					 regTabPtr,
                                          disk_page != RNIL);
-       set_change_mask_state(regOperPtr, DELETE_CHANGES);
        sendTUPKEYCONF(signal, &req_struct, regOperPtr);
        return;
      }
@@ -991,26 +980,31 @@ int Dbtup::handleUpdateReq(Signal* signa
                            KeyReqStruct* req_struct,
 			   bool disk) 
 {
-  Uint32 *dst;
+  Tuple_header *dst;
   Tuple_header *base= req_struct->m_tuple_ptr, *org;
-  if ((dst= c_undo_buffer.alloc_copy_tuple(&operPtrP->m_copy_tuple_location,
-					   regTabPtr->total_rec_size)) == 0)
+  Uint32 * change_mask_ptr;
+  if ((dst= alloc_copy_tuple(regTabPtr, &operPtrP->m_copy_tuple_location))== 0)
   {
     terrorCode= ZMEM_NOMEM_ERROR;
     goto error;
   }
 
   Uint32 tup_version;
+  change_mask_ptr = get_change_mask_ptr(regTabPtr, dst);
   if(operPtrP->is_first_operation())
   {
     org= req_struct->m_tuple_ptr;
     tup_version= org->get_tuple_version();
+    clear_change_mask_info(regTabPtr, change_mask_ptr);
   }
   else
   {
     Operationrec* prevOp= req_struct->prevOpPtr.p;
     tup_version= prevOp->tupVersion;
-    org= (Tuple_header*)c_undo_buffer.get_ptr(&prevOp->m_copy_tuple_location);
+    org= get_copy_tuple(regTabPtr, &prevOp->m_copy_tuple_location);
+    copy_change_mask_info(regTabPtr,
+                          change_mask_ptr,
+                          get_change_mask_ptr(regTabPtr, org));
   }
 
   /**
@@ -1024,7 +1018,7 @@ int Dbtup::handleUpdateReq(Signal* signa
     goto error;
   }
 
-  req_struct->m_tuple_ptr= (Tuple_header*)dst;
+  req_struct->m_tuple_ptr= dst;
 
   union {
     Uint32 sizes[4];
@@ -1073,6 +1067,10 @@ int Dbtup::handleUpdateReq(Signal* signa
       return -1;
   }
   
+  update_change_mask_info(regTabPtr,
+                          change_mask_ptr,
+                          req_struct->changeMask.rep.data);
+
   if (regTabPtr->need_shrink())
   {  
     shrink_tuple(req_struct, sizes+2, regTabPtr, disk);
@@ -1327,7 +1325,8 @@ int Dbtup::handleInsertReq(Signal* signa
 {
   Uint32 tup_version = 1;
   Fragrecord* regFragPtr = fragPtr.p;
-  Uint32 *dst, *ptr= 0;
+  Uint32 *ptr= 0;
+  Tuple_header *dst;
   Tuple_header *base= req_struct->m_tuple_ptr, *org= base;
   Tuple_header *tuple_ptr;
     
@@ -1353,13 +1352,14 @@ int Dbtup::handleInsertReq(Signal* signa
     goto undo_buffer_error;
   }
 
-  dst= c_undo_buffer.alloc_copy_tuple(&regOperPtr.p->m_copy_tuple_location,
-				      regTabPtr->total_rec_size);
+  dst= alloc_copy_tuple(regTabPtr, &regOperPtr.p->m_copy_tuple_location);
+
   if (unlikely(dst == 0))
   {
     goto undo_buffer_error;
   }
-  tuple_ptr= req_struct->m_tuple_ptr= (Tuple_header*)dst;
+  tuple_ptr= req_struct->m_tuple_ptr= dst;
+  set_change_mask_info(regTabPtr, get_change_mask_ptr(regTabPtr, dst));
 
   if(mem_insert)
   {
@@ -1373,7 +1373,7 @@ int Dbtup::handleInsertReq(Signal* signa
     tup_version= prevOp->tupVersion + 1;
     
     if(!prevOp->is_first_operation())
-      org= (Tuple_header*)c_undo_buffer.get_ptr(&prevOp->m_copy_tuple_location);
+      org= get_copy_tuple(regTabPtr, &prevOp->m_copy_tuple_location);
     if (regTabPtr->need_expand())
     {
       expand_tuple(req_struct, sizes, org, regTabPtr, !disk_insert);
@@ -1675,16 +1675,18 @@ int Dbtup::handleDeleteReq(Signal* signa
     Operationrec* prevOp= req_struct->prevOpPtr.p;
     regOperPtr->tupVersion= prevOp->tupVersion;
     // make copy since previous op is committed before this one
-    const Uint32* org = c_undo_buffer.get_ptr(&prevOp->m_copy_tuple_location);
-    Uint32* dst = c_undo_buffer.alloc_copy_tuple(
-        &regOperPtr->m_copy_tuple_location, regTabPtr->total_rec_size);
+    const Tuple_header* org = get_copy_tuple(regTabPtr,
+                                             &prevOp->m_copy_tuple_location);
+    Tuple_header* dst = alloc_copy_tuple(regTabPtr,
+                                         &regOperPtr->m_copy_tuple_location);
     if (dst == 0) {
       terrorCode = ZMEM_NOMEM_ERROR;
       goto error;
     }
     memcpy(dst, org, regTabPtr->total_rec_size << 2);
-    req_struct->m_tuple_ptr = (Tuple_header*)dst;
-  } 
+    req_struct->m_tuple_ptr = dst;
+    set_change_mask_info(regTabPtr, get_change_mask_ptr(regTabPtr, dst));
+  }
   else 
   {
     regOperPtr->tupVersion= req_struct->m_tuple_ptr->get_tuple_version();
@@ -3495,8 +3497,8 @@ Dbtup::nr_read_pk(Uint32 fragPtrI, 
       Uint32 opPtrI= req_struct.m_tuple_ptr->m_operation_ptr_i;
       Operationrec* opPtrP= c_operation_pool.getPtr(opPtrI);
       ndbassert(!opPtrP->m_copy_tuple_location.isNull());
-      req_struct.m_tuple_ptr= (Tuple_header*)
-	c_undo_buffer.get_ptr(&opPtrP->m_copy_tuple_location);
+      req_struct.m_tuple_ptr=
+        get_copy_tuple(tablePtr.p, &opPtrP->m_copy_tuple_location);
       copy = true;
     }
     req_struct.check_offset[MM]= tablePtr.p->get_check_offset(MM);
diff -Nrup a/storage/ndb/src/kernel/blocks/dbtup/DbtupIndex.cpp b/storage/ndb/src/kernel/blocks/dbtup/DbtupIndex.cpp
--- a/storage/ndb/src/kernel/blocks/dbtup/DbtupIndex.cpp	2008-01-30 12:26:26 +01:00
+++ b/storage/ndb/src/kernel/blocks/dbtup/DbtupIndex.cpp	2008-03-19 13:56:57 +01:00
@@ -158,8 +158,8 @@ Dbtup::tuxReadAttrs(Uint32 fragPtrI,
       if (opPtr.p->tupVersion == tupVersion) {
 	jam();
 	if (!opPtr.p->m_copy_tuple_location.isNull()) {
-	  req_struct.m_tuple_ptr= (Tuple_header*)
-	    c_undo_buffer.get_ptr(&opPtr.p->m_copy_tuple_location);
+	  req_struct.m_tuple_ptr=
+	    get_copy_tuple(tablePtr.p, &opPtr.p->m_copy_tuple_location);
         }
 	break;
       }
@@ -238,8 +238,8 @@ Dbtup::tuxReadPk(Uint32 fragPtrI, Uint32
       Uint32 opPtrI= req_struct.m_tuple_ptr->m_operation_ptr_i;
       Operationrec* opPtrP= c_operation_pool.getPtr(opPtrI);
       ndbassert(!opPtrP->m_copy_tuple_location.isNull());
-      req_struct.m_tuple_ptr= (Tuple_header*)
-	c_undo_buffer.get_ptr(&opPtrP->m_copy_tuple_location);
+      req_struct.m_tuple_ptr=
+	get_copy_tuple(tablePtr.p, &opPtrP->m_copy_tuple_location);
     }
     prepare_read(&req_struct, tablePtr.p, false);
     
diff -Nrup a/storage/ndb/src/kernel/blocks/dbtup/DbtupMeta.cpp b/storage/ndb/src/kernel/blocks/dbtup/DbtupMeta.cpp
--- a/storage/ndb/src/kernel/blocks/dbtup/DbtupMeta.cpp	2007-10-23 11:29:27 +02:00
+++ b/storage/ndb/src/kernel/blocks/dbtup/DbtupMeta.cpp	2008-03-19 13:56:57 +01:00
@@ -1161,6 +1161,10 @@ Dbtup::computeTableMetaData(Tablerec *re
   total_rec_size+= Tuple_header::HeaderSize;
   if(regTabPtr->m_no_of_disk_attributes)
     total_rec_size+= Tuple_header::HeaderSize;
+
+  /* Room for changemask */
+  total_rec_size += (regTabPtr->m_no_of_attributes + 31) >> 5;
+
   regTabPtr->total_rec_size= total_rec_size;
 
   setUpQueryRoutines(regTabPtr);
diff -Nrup a/storage/ndb/src/kernel/blocks/dbtup/DbtupRoutines.cpp b/storage/ndb/src/kernel/blocks/dbtup/DbtupRoutines.cpp
--- a/storage/ndb/src/kernel/blocks/dbtup/DbtupRoutines.cpp	2007-10-26 12:07:12 +02:00
+++ b/storage/ndb/src/kernel/blocks/dbtup/DbtupRoutines.cpp	2008-03-19 13:56:57 +01:00
@@ -1510,13 +1510,6 @@ int Dbtup::updateAttributes(KeyReqStruct
       jam();
       req_struct->attr_descriptor= attrDescriptor;
       req_struct->changeMask.set(attributeId);
-      if (attributeId >= 64) {
-        if (req_struct->max_attr_id_updated < attributeId) {
-          Uint32 no_changed_attrs= req_struct->no_changed_attrs;
-          req_struct->max_attr_id_updated= attributeId;
-          req_struct->no_changed_attrs= no_changed_attrs + 1;
-        }
-      }
       if ((this->*f)(inBuffer,
                      req_struct,
                      attributeOffset)) {
diff -Nrup a/storage/ndb/src/kernel/blocks/dbtup/DbtupTrigger.cpp b/storage/ndb/src/kernel/blocks/dbtup/DbtupTrigger.cpp
--- a/storage/ndb/src/kernel/blocks/dbtup/DbtupTrigger.cpp	2008-01-30 12:26:26 +01:00
+++ b/storage/ndb/src/kernel/blocks/dbtup/DbtupTrigger.cpp	2008-03-19 13:56:57 +01:00
@@ -475,8 +475,8 @@ void Dbtup::checkDetachedTriggers(KeyReq
   switch (save_type) {
   case ZUPDATE:
   case ZINSERT:
-    req_struct->m_tuple_ptr = (Tuple_header*)
-      c_undo_buffer.get_ptr(&regOperPtr->m_copy_tuple_location);
+    req_struct->m_tuple_ptr =
+      get_copy_tuple(regTablePtr, &regOperPtr->m_copy_tuple_location);
     break;
   }
 
@@ -853,8 +853,9 @@ bool Dbtup::readTriggerInfo(TupTriggerDa
       !regOperPtr->is_first_operation())
   {
     jam();
-    req_struct->m_tuple_ptr= (Tuple_header*)
-      c_undo_buffer.get_ptr(&req_struct->prevOpPtr.p->m_copy_tuple_location);
+    req_struct->m_tuple_ptr=
+      get_copy_tuple(regTabPtr,
+                     &req_struct->prevOpPtr.p->m_copy_tuple_location);
   }
 
   if (regTabPtr->need_expand(disk)) 
@@ -947,10 +948,9 @@ bool Dbtup::readTriggerInfo(TupTriggerDa
     }
     else
     {
-      Uint32 *ptr= 
-	c_undo_buffer.get_ptr(&req_struct->prevOpPtr.p->m_copy_tuple_location);
-
-      req_struct->m_tuple_ptr= (Tuple_header*)ptr;
+      req_struct->m_tuple_ptr =
+        get_copy_tuple(regTabPtr,
+                       &req_struct->prevOpPtr.p->m_copy_tuple_location);
     }
 
     if (regTabPtr->need_expand(disk)) 
diff -Nrup a/storage/ndb/src/kernel/blocks/dbtup/Undo_buffer.cpp b/storage/ndb/src/kernel/blocks/dbtup/Undo_buffer.cpp
--- a/storage/ndb/src/kernel/blocks/dbtup/Undo_buffer.cpp	2008-02-08 15:24:49 +01:00
+++ b/storage/ndb/src/kernel/blocks/dbtup/Undo_buffer.cpp	2008-03-19 13:56:57 +01:00
@@ -115,7 +115,7 @@ Undo_buffer::free_copy_tuple(Local_key* 
 }
 
 Uint32 *
-Undo_buffer::get_ptr(Local_key* key)
+Undo_buffer::get_ptr(const Local_key* key)
 {
   return get_page(m_mm, key->m_page_no)->m_data+key->m_page_idx;
 }
diff -Nrup a/storage/ndb/src/kernel/blocks/dbtup/Undo_buffer.hpp b/storage/ndb/src/kernel/blocks/dbtup/Undo_buffer.hpp
--- a/storage/ndb/src/kernel/blocks/dbtup/Undo_buffer.hpp	2007-02-02 17:22:34 +01:00
+++ b/storage/ndb/src/kernel/blocks/dbtup/Undo_buffer.hpp	2008-03-19 13:56:57 +01:00
@@ -46,7 +46,7 @@ struct Undo_buffer 
   /**
    * Get pointer to copy tuple
    */
-  Uint32 * get_ptr(Local_key* key);
+  Uint32 * get_ptr(const Local_key* key);
   
 private:
   class Ndbd_mem_manager* m_mm;
diff -Nrup a/storage/ndb/test/ndbapi/test_event.cpp b/storage/ndb/test/ndbapi/test_event.cpp
--- a/storage/ndb/test/ndbapi/test_event.cpp	2008-02-20 15:08:18 +01:00
+++ b/storage/ndb/test/ndbapi/test_event.cpp	2008-03-19 13:56:57 +01:00
@@ -2173,6 +2173,169 @@ runNFSubscribe(NDBT_Context* ctx, NDBT_S
   return NDBT_OK;
 }
 
+int
+runBug35208_createTable(NDBT_Context* ctx, NDBT_Step* step)
+{
+  NdbDictionary::Table tab = *ctx->getTab();
+
+  while (tab.getNoOfColumns() < 100)
+  {
+    BaseString name;
+    NdbDictionary::Column col;
+    name.assfmt("COL_%d", tab.getNoOfColumns());
+    col.setName(name.c_str());
+    col.setType(NdbDictionary::Column::Unsigned);
+    col.setLength(1);
+    col.setNullable(false);
+    col.setPrimaryKey(false);
+    tab.addColumn(col);
+  }
+
+  NdbDictionary::Dictionary* dict = GETNDB(step)->getDictionary();
+  dict->dropTable(tab.getName());
+  dict->createTable(tab);
+
+  const NdbDictionary::Table* pTab = dict->getTable(tab.getName());
+  ctx->setTab(pTab);
+
+  return NDBT_OK;
+}
+
+#define UPDATE_COL 66
+
+int
+runBug35208(NDBT_Context* ctx, NDBT_Step* step)
+{
+  Ndb* ndb= GETNDB(step);
+  const NdbDictionary::Table * table= ctx->getTab();
+
+  char buf[1024];
+  sprintf(buf, "%s_EVENT", table->getName());
+  NdbEventOperation *pOp = ndb->createEventOperation(buf);
+  if ( pOp == NULL ) {
+    g_err << "Event operation creation failed on %s" << buf << endl;
+    return NDBT_FAILED;
+  }
+
+  int result = NDBT_OK;
+  HugoTransactions hugoTrans(* table);
+
+  char col[100];
+  BaseString::snprintf(col, sizeof(col), "COL_%u", UPDATE_COL);
+
+  int i;
+  int n_columns= table->getNoOfColumns();
+  NdbRecAttr* recAttr[1024];
+  NdbRecAttr* recAttrPre[1024];
+  for (i = 0; i < n_columns; i++) {
+    recAttr[i]    = pOp->getValue(table->getColumn(i)->getName());
+    recAttrPre[i] = pOp->getPreValue(table->getColumn(i)->getName());
+  }
+
+  if (pOp->execute())
+  { // This starts changes to "start flowing"
+    g_err << "execute operation execution failed: \n";
+    g_err << pOp->getNdbError().code << " "
+	  << pOp->getNdbError().message << endl;
+    goto err;
+  }
+
+  hugoTrans.loadTable(GETNDB(step), ctx->getNumRecords());
+
+  for (int i = 0; i<ctx->getNumLoops(); i++)
+  {
+    ndbout_c("testing %u updates", (i + 1));
+    NdbTransaction* pTrans = ndb->startTransaction();
+    for (int m = 0; m<(i+1); m++)
+    {
+      for (int r = 0; r<ctx->getNumRecords(); r++)
+      {
+        NdbOperation* pOp = pTrans->getNdbOperation(table->getName());
+        pOp->updateTuple();
+        HugoOperations hop(* table);
+        hop.equalForRow(pOp, r);
+        pOp->setValue(col, rand());
+      }
+      if (pTrans->execute(NoCommit) != 0)
+      {
+        ndbout << pTrans->getNdbError() << endl;
+        goto err;
+      }
+    }
+    if (pTrans->execute(Commit) != 0)
+    {
+      ndbout << pTrans->getNdbError() << endl;
+      goto err;
+    }
+
+    Uint64 gci;
+    pTrans->getGCI(&gci);
+    ndbout_c("set(LastGCI_hi): %u/%u",
+             Uint32(gci >> 32),
+             Uint32(gci));
+    ctx->setProperty("LastGCI_lo", Uint32(gci));
+    ctx->setProperty("LastGCI_hi", Uint32(gci >> 32));
+    if(ctx->getPropertyWait("LastGCI_hi", ~(Uint32)0))
+    {
+      g_err << "FAIL " << __LINE__ << endl;
+      goto err;
+    }
+
+    Uint32 bug = 0;
+    Uint32 cnt = 0;
+    Uint64 curr_gci = 0;
+    while(curr_gci <= gci)
+    {
+      ndb->pollEvents(100, &curr_gci);
+      NdbEventOperation* tmp = 0;
+      while ((tmp= ndb->nextEvent()) != 0)
+      {
+        if (tmp->getEventType() == NdbDictionary::Event::TE_UPDATE)
+        {
+          cnt++;
+          bool first = true;
+          for (int c = 0; c<table->getNoOfColumns(); c++)
+          {
+            if (recAttr[c]->isNULL() >= 0)
+            {
+              /**
+               * Column has value...it should be PK or column we updated
+               */
+              if (c != UPDATE_COL &&
+                  table->getColumn(c)->getPrimaryKey() == false)
+              {
+                bug++;
+                if (first)
+                {
+                  first = false;
+                  printf("Detect (incorrect) update value for: ");
+                }
+                printf("%u ", c);
+                result = NDBT_FAILED;
+              }
+            }
+          }
+          if (!first)
+            printf("\n");
+        }
+      }
+    }
+    ndbout_c("found %u updates bugs: %u", cnt, bug);
+  }
+
+  ndb->dropEventOperation(pOp);
+  ctx->stopTest();
+
+  return result;
+
+err:
+  ndb->dropEventOperation(pOp);
+
+  return NDBT_FAILED;
+}
+
+
+
 /** Telco 6.3 **/
 
 NDBT_TESTSUITE(test_event);
@@ -2338,6 +2501,16 @@ TESTCASE("Bug33793", ""){
   STEP(runEventListenerUntilStopped);
   STEP(runBug33793);
   FINALIZER(runDropEvent);
+}
+TESTCASE("Bug35208", ""){
+  INITIALIZER(runBug35208_createTable);
+  INITIALIZER(runCreateEvent);
+  INITIALIZER(runCreateShadowTable);
+  STEP(runBug35208);
+  STEP(runEventApplier);
+  FINALIZER(runDropEvent);
+  FINALIZER(runVerify);
+  FINALIZER(runDropShadowTable);
 }
 NDBT_TESTSUITE_END(test_event);
 
diff -Nrup a/storage/ndb/test/run-test/daily-basic-tests.txt b/storage/ndb/test/run-test/daily-basic-tests.txt
--- a/storage/ndb/test/run-test/daily-basic-tests.txt	2008-03-09 10:50:03 +01:00
+++ b/storage/ndb/test/run-test/daily-basic-tests.txt	2008-03-19 13:56:57 +01:00
@@ -1102,3 +1102,7 @@ max-time: 300
 cmd: testNodeRestart
 args: -n Bug34702 T1
 
+max-time: 600
+cmd: test_event
+args: -n Bug35208 T1
+
Thread
bk commit into 5.1 tree (jonas:1.2561) BUG#35208jonas19 Mar