List:Commits« Previous MessageNext Message »
From:tomas Date:May 18 2006 11:38pm
Subject:bk commit into 5.1 tree (tomas:1.2154) BUG#17610
View as plain text  
Below is the list of changes that have just been committed into a local
5.1 repository of tomas. When tomas 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
  1.2154 06/05/18 23:38:07 tomas@stripped +10 -0
      Bug #19395 mysqld does not always detect cluster shutdown
      Bug #17610 ndbapi: dropEventOperation leaves object behind, memleak

  storage/ndb/src/ndbapi/NdbEventOperationImpl.hpp
    1.22 06/05/18 23:37:53 tomas@stripped +9 -5
    Bug #17610 ndbapi: dropEventOperation leaves object behind, memleak

  storage/ndb/src/ndbapi/NdbEventOperationImpl.cpp
    1.58 06/05/18 23:37:53 tomas@stripped +230 -108
    Bug #17610 ndbapi: dropEventOperation leaves object behind, memleak

  storage/ndb/src/ndbapi/Ndb.cpp
    1.70 06/05/18 23:37:53 tomas@stripped +6 -0
    Bug #19395 mysqld does not always detect cluster shutdown

  storage/ndb/src/kernel/blocks/suma/Suma.cpp
    1.42 06/05/18 23:37:53 tomas@stripped +16 -1
    Bug #17610 ndbapi: dropEventOperation leaves object behind, memleak

  storage/ndb/include/ndbapi/NdbDictionary.hpp
    1.75 06/05/18 23:37:53 tomas@stripped +2 -1
    Bug #17610 ndbapi: dropEventOperation leaves object behind, memleak

  storage/ndb/include/ndbapi/Ndb.hpp
    1.50 06/05/18 23:37:53 tomas@stripped +1 -0
    Bug #19395 mysqld does not always detect cluster shutdown

  sql/ha_ndbcluster_binlog.cc
    1.55 06/05/18 23:37:53 tomas@stripped +3 -0
    Bug #19395 mysqld does not always detect cluster shutdown

  mysql-test/t/ndb_autodiscover3.test
    1.4 06/05/18 23:37:53 tomas@stripped +4 -0
    Bug #19395 mysqld does not always detect cluster shutdown

  mysql-test/t/disabled.def
    1.157 06/05/18 23:37:53 tomas@stripped +1 -1
    Bug #19395 mysqld does not always detect cluster shutdown

  mysql-test/r/ndb_autodiscover3.result
    1.5 06/05/18 23:37:53 tomas@stripped +4 -0
    Bug #19395 mysqld does not always detect cluster shutdown

# This is a BitKeeper patch.  What follows are the unified diffs for the
# set of deltas contained in the patch.  The rest of the patch, the part
# that BitKeeper cares about, is below these diffs.
# User:	tomas
# Host:	poseidon.ndb.mysql.com
# Root:	/home/tomas/mysql-5.1-new-ndb

--- 1.156/mysql-test/t/disabled.def	2006-05-16 20:58:11 +02:00
+++ 1.157/mysql-test/t/disabled.def	2006-05-18 23:37:53 +02:00
@@ -16,7 +16,7 @@
 events_logs_tests        : BUG#17619 2006-05-16 andrey  Test case problems
 ndb_autodiscover         : BUG#18952 2006-02-16 jmiller Needs to be fixed w.r.t binlog
 ndb_autodiscover2        : BUG#18952 2006-02-16 jmiller Needs to be fixed w.r.t binlog
-ndb_binlog_discover      : BUG#19395 2006-04-28 tomas/knielsen mysqld does not always
detect cluster shutdown
+#ndb_binlog_discover      : BUG#19395 2006-04-28 tomas/knielsen mysqld does not always
detect cluster shutdown
 #ndb_cache2               : BUG#18597 2006-03-28 brian simultaneous drop table and ndb
statistics update triggers node failure
 #ndb_cache_multi2         : BUG#18597 2006-04-10 kent  simultaneous drop table and ndb
statistics update triggers node failure
 ndb_load                 : BUG#17233 2006-05-04 tomas failed load data from infile causes
mysqld dbug_assert, binlog not flushed

--- 1.49/storage/ndb/include/ndbapi/Ndb.hpp	2006-05-04 13:58:06 +02:00
+++ 1.50/storage/ndb/include/ndbapi/Ndb.hpp	2006-05-18 23:37:53 +02:00
@@ -1262,6 +1262,7 @@
   
 
 #ifndef DOXYGEN_SHOULD_SKIP_INTERNAL
+  int flushIncompleteEvents(Uint64 gci);
   NdbEventOperation *getEventOperation(NdbEventOperation* eventOp= 0);
   Uint64 getLatestGCI();
   void forceGCP();

--- 1.74/storage/ndb/include/ndbapi/NdbDictionary.hpp	2006-05-04 13:58:06 +02:00
+++ 1.75/storage/ndb/include/ndbapi/NdbDictionary.hpp	2006-05-18 23:37:53 +02:00
@@ -1132,7 +1132,8 @@
       _TE_NODE_FAILURE=10,
       _TE_SUBSCRIBE=11,
       _TE_UNSUBSCRIBE=12,
-      _TE_NUL=13 // internal (e.g. INS o DEL within same GCI)
+      _TE_NUL=13, // internal (e.g. INS o DEL within same GCI)
+      _TE_ACTIVE=14 // internal (node becomes active)
     };
 #endif
     /**

--- 1.41/storage/ndb/src/kernel/blocks/suma/Suma.cpp	2006-03-27 18:53:16 +02:00
+++ 1.42/storage/ndb/src/kernel/blocks/suma/Suma.cpp	2006-05-18 23:37:53 +02:00
@@ -2649,6 +2649,22 @@
                            SubscriptionPtr subPtr,
                            SubscriberPtr subbPtr)
 {
+  SubTableData * data  = (SubTableData*)signal->getDataPtrSend();
+
+  if (table_event == NdbDictionary::Event::_TE_SUBSCRIBE)
+  {
+    data->gci            = m_last_complete_gci + 1;
+    data->tableId        = subPtr.p->m_tableId;
+    data->operation      = NdbDictionary::Event::_TE_ACTIVE;
+    data->ndbd_nodeid    = refToNode(reference());
+    data->changeMask     = 0;
+    data->totalLen       = 0;
+    data->req_nodeid     = refToNode(subbPtr.p->m_senderRef);
+    data->senderData     = subbPtr.p->m_senderData;
+    sendSignal(subbPtr.p->m_senderRef, GSN_SUB_TABLE_DATA, signal,
+               SubTableData::SignalLength, JBB);
+  }
+
   if (!(subPtr.p->m_options & Subscription::REPORT_SUBSCRIBE))
   {
     return;
@@ -2663,7 +2679,6 @@
   ndbout_c("reportAllSubscribers  subPtr.i: %d  subPtr.p->n_subscribers: %d",
            subPtr.i, subPtr.p->n_subscribers);
 //#endif
-  SubTableData * data  = (SubTableData*)signal->getDataPtrSend();
   data->gci            = m_last_complete_gci + 1;
   data->tableId        = subPtr.p->m_tableId;
   data->operation      = table_event;

--- 1.69/storage/ndb/src/ndbapi/Ndb.cpp	2006-05-16 20:56:38 +02:00
+++ 1.70/storage/ndb/src/ndbapi/Ndb.cpp	2006-05-18 23:37:53 +02:00
@@ -1324,6 +1324,12 @@
   return theEventBuffer->pollEvents(aMillisecondNumber, latestGCI);
 }
 
+int
+Ndb::flushIncompleteEvents(Uint64 gci)
+{
+  return theEventBuffer->flushIncompleteEvents(gci);
+}
+
 NdbEventOperation *Ndb::nextEvent()
 {
   return theEventBuffer->nextEvent();

--- 1.57/storage/ndb/src/ndbapi/NdbEventOperationImpl.cpp	2006-05-10 13:32:50 +02:00
+++ 1.58/storage/ndb/src/ndbapi/NdbEventOperationImpl.cpp	2006-05-18 23:37:53 +02:00
@@ -153,11 +153,14 @@
 
   m_state= EO_CREATED;
 
+  m_node_bit_mask.clear();
 #ifdef ndb_event_stores_merge_events_flag
   m_mergeEvents = m_eventImpl->m_mergeEvents;
 #else
-   m_mergeEvents = false;
+  m_mergeEvents = false;
 #endif
+  m_ref_count = 0;
+  DBUG_PRINT("info", ("m_ref_count = 0 for op: %p", this));
 
   m_has_error= 0;
 
@@ -530,7 +533,11 @@
       }
     }
     if (r == 0)
+    {
+      m_ref_count++;
+      DBUG_PRINT("info", ("m_ref_count: %u for op: %p", m_ref_count, this));
       DBUG_RETURN(0);
+    }
   }
   //Error
   m_state= EO_ERROR;
@@ -657,80 +664,79 @@
 int
 NdbEventOperationImpl::receive_event()
 {
-  DBUG_ENTER_EVENT("NdbEventOperationImpl::receive_event");
-
   Uint32 operation= (Uint32)m_data_item->sdata->operation;
-  DBUG_PRINT_EVENT("info",("sdata->operation %u",operation));
-
-  if (operation == NdbDictionary::Event::_TE_ALTER)
+  if (unlikely(operation >= NdbDictionary::Event::_TE_FIRST_NON_DATA_EVENT))
   {
-    // Parse the new table definition and
-    // create a table object
-    NdbDictionary::Dictionary *myDict = m_ndb->getDictionary();
-    NdbDictionaryImpl *dict = & NdbDictionaryImpl::getImpl(*myDict);
-    NdbError error;
-    NdbDictInterface dif(error);
-    NdbTableImpl *at;
-    m_change_mask = m_data_item->sdata->changeMask;
-    error.code = dif.parseTableInfo(&at,
-                                    (Uint32*)m_buffer.get_data(), 
-                                    m_buffer.length() / 4, 
-                                    true);
-    m_buffer.clear();
-    if (at)
+    DBUG_ENTER("NdbEventOperationImpl::receive_event");
+    DBUG_PRINT("info",("sdata->operation %u  this: %p", operation, this));
+    if (operation == NdbDictionary::Event::_TE_ALTER)
+    {
+      // Parse the new table definition and
+      // create a table object
+      NdbDictionary::Dictionary *myDict = m_ndb->getDictionary();
+      NdbDictionaryImpl *dict = & NdbDictionaryImpl::getImpl(*myDict);
+      NdbError error;
+      NdbDictInterface dif(error);
+      NdbTableImpl *at;
+      m_change_mask = m_data_item->sdata->changeMask;
+      error.code = dif.parseTableInfo(&at,
+                                      (Uint32*)m_buffer.get_data(), 
+                                      m_buffer.length() / 4, 
+                                      true);
+      m_buffer.clear();
+      if (unlikely(!at))
+      {
+        DBUG_PRINT("info", ("Failed to parse DictTabInfo error %u", 
+                                  error.code));
+        ndbout_c("Failed to parse DictTabInfo error %u", error.code);
+        DBUG_RETURN(1);
+      }
       at->buildColumnHash();
-    else
-    {
-      DBUG_PRINT_EVENT("info", ("Failed to parse DictTabInfo error %u", 
-                                error.code));
-      DBUG_RETURN_EVENT(1);
-    }
-
-    NdbTableImpl *tmp_table_impl= m_eventImpl->m_tableImpl;
-    m_eventImpl->m_tableImpl = at;
-
-    DBUG_PRINT("info", ("switching table impl 0x%x -> 0x%x",
-                        tmp_table_impl, at));
-
-    // change the rec attrs to refer to the new table object
-    int i;
-    for (i = 0; i < 2; i++)
-    {
-      NdbRecAttr *p = theFirstPkAttrs[i];
-      while (p)
+      
+      NdbTableImpl *tmp_table_impl= m_eventImpl->m_tableImpl;
+      m_eventImpl->m_tableImpl = at;
+      
+      DBUG_PRINT("info", ("switching table impl 0x%x -> 0x%x",
+                          tmp_table_impl, at));
+      
+      // change the rec attrs to refer to the new table object
+      int i;
+      for (i = 0; i < 2; i++)
       {
-        int no = p->getColumn()->getColumnNo();
-        NdbColumnImpl *tAttrInfo = at->getColumn(no);
-        DBUG_PRINT("info", ("rec_attr: 0x%x  "
-                            "switching column impl 0x%x -> 0x%x",
-                            p, p->m_column, tAttrInfo));
-        p->m_column = tAttrInfo;
-        p = p->next();
+        NdbRecAttr *p = theFirstPkAttrs[i];
+        while (p)
+        {
+          int no = p->getColumn()->getColumnNo();
+          NdbColumnImpl *tAttrInfo = at->getColumn(no);
+          DBUG_PRINT("info", ("rec_attr: 0x%x  "
+                              "switching column impl 0x%x -> 0x%x",
+                              p, p->m_column, tAttrInfo));
+          p->m_column = tAttrInfo;
+          p = p->next();
+        }
       }
-    }
-    for (i = 0; i < 2; i++)
-    {
-      NdbRecAttr *p = theFirstDataAttrs[i];
-      while (p)
+      for (i = 0; i < 2; i++)
       {
-        int no = p->getColumn()->getColumnNo();
-        NdbColumnImpl *tAttrInfo = at->getColumn(no);
-        DBUG_PRINT("info", ("rec_attr: 0x%x  "
-                            "switching column impl 0x%x -> 0x%x",
-                            p, p->m_column, tAttrInfo));
-        p->m_column = tAttrInfo;
-        p = p->next();
+        NdbRecAttr *p = theFirstDataAttrs[i];
+        while (p)
+        {
+          int no = p->getColumn()->getColumnNo();
+          NdbColumnImpl *tAttrInfo = at->getColumn(no);
+          DBUG_PRINT("info", ("rec_attr: 0x%x  "
+                              "switching column impl 0x%x -> 0x%x",
+                              p, p->m_column, tAttrInfo));
+          p->m_column = tAttrInfo;
+          p = p->next();
+        }
       }
+      if (tmp_table_impl) 
+        delete tmp_table_impl;
     }
-    if (tmp_table_impl) 
-      delete tmp_table_impl;
-  }
-
-  if (unlikely(operation >= NdbDictionary::Event::_TE_FIRST_NON_DATA_EVENT))
-  {
-    DBUG_RETURN_EVENT(1);
+    DBUG_RETURN(1);
   }
 
+  DBUG_ENTER_EVENT("NdbEventOperationImpl::receive_event");
+  DBUG_PRINT_EVENT("info",("sdata->operation %u  this: %p", operation, this));
   // now move the data into the RecAttrs
     
   int is_update= operation == NdbDictionary::Event::_TE_UPDATE;
@@ -1089,6 +1095,32 @@
   return ret;
 }
 
+int
+NdbEventBuffer::flushIncompleteEvents(Uint64 gci)
+{
+  /**
+   *  Find min complete gci
+   */
+  Uint32 i;
+  Uint32 sz= m_active_gci.size();
+  Gci_container* array = (Gci_container*)m_active_gci.getBase();
+  for(i = 0; i < sz; i++)
+  {
+    Gci_container* tmp = array + i;
+    if (tmp->m_gci < gci)
+    {
+      // we have found an old not-completed gci, remove it
+      if(!tmp->m_data.is_empty())
+      {
+        free_list(tmp->m_data);
+      }
+      tmp->~Gci_container();
+      bzero(tmp, sizeof(Gci_container));
+    }
+  }
+  return 0;
+}
+
 NdbEventOperation *
 NdbEventBuffer::nextEvent()
 {
@@ -1157,7 +1189,10 @@
         }
         EventBufData_list::Gci_ops *gci_ops = m_available_data.first_gci_ops();
         while (gci_ops && op->getGCI() > gci_ops->m_gci)
+        {
+          deleteUsedEventOperations();
           gci_ops = m_available_data.next_gci_ops();
+        }
         assert(gci_ops && (op->getGCI() == gci_ops->m_gci));
 	DBUG_RETURN_EVENT(op->m_facade);
       }
@@ -1177,7 +1212,10 @@
   // free all "per gci unique" collected operations
   EventBufData_list::Gci_ops *gci_ops = m_available_data.first_gci_ops();
   while (gci_ops)
+  {
+    deleteUsedEventOperations();
     gci_ops = m_available_data.next_gci_ops();
+  }
   DBUG_RETURN_EVENT(0);
 }
 
@@ -1191,31 +1229,38 @@
     EventBufData_list::Gci_op g = gci_ops->m_gci_op_list[(*iter)++];
     if (event_types != NULL)
       *event_types = g.event_types;
-    DBUG_PRINT("info", ("gci: %d", (unsigned)gci_ops->m_gci));
+    DBUG_PRINT("info", ("gci: %d  g.op: %x  g.event_types: %x",
+                        (unsigned)gci_ops->m_gci, g.op, g.event_types));
     DBUG_RETURN(g.op);
   }
   DBUG_RETURN(NULL);
 }
 
 void
-NdbEventBuffer::lock()
-{
-  NdbMutex_Lock(m_mutex);
-}
-void
-NdbEventBuffer::unlock()
-{
-  NdbMutex_Unlock(m_mutex);
-}
-void
-NdbEventBuffer::add_drop_lock()
-{
-  NdbMutex_Lock(p_add_drop_mutex);
-}
-void
-NdbEventBuffer::add_drop_unlock()
+NdbEventBuffer::deleteUsedEventOperations()
 {
-  NdbMutex_Unlock(p_add_drop_mutex);
+  Uint32 iter= 0;
+  const NdbEventOperation *op_f;
+  while ((op_f= getGCIEventOperations(&iter, NULL)) != NULL)
+  {
+    NdbEventOperationImpl *op = &op_f->m_impl;
+    DBUG_ASSERT(op->m_ref_count > 0);
+    op->m_ref_count--;
+    DBUG_PRINT("info", ("m_ref_count: %u for op: %p", op->m_ref_count, op));
+    if (op->m_ref_count == 0)
+    {
+      DBUG_PRINT("info", ("deleting op: %p", op));
+      DBUG_ASSERT(op->m_node_bit_mask.isclear());
+      if (op->m_next)
+        op->m_next->m_prev = op->m_prev;
+      if (op->m_prev)
+        op->m_prev->m_next = op->m_next;
+      else
+        m_dropped_ev_op = op->m_next;
+      ndbout_c("deleting NdbEventOperation %p", op->m_facade);
+      delete op->m_facade;
+    }
+  }
 }
 
 static
@@ -1469,6 +1514,10 @@
 void
 NdbEventBuffer::report_node_failure(Uint32 node_id)
 {
+  NdbEventOperation* op= m_ndb->getEventOperation(0);
+  if (op == 0)
+    return;
+
   DBUG_ENTER("NdbEventBuffer::report_node_failure");
   SubTableData data;
   LinearSectionPtr ptr[3];
@@ -1484,12 +1533,20 @@
   /**
    * Insert this event for each operation
    */
-  NdbEventOperation* op= 0;
-  while((op = m_ndb->getEventOperation(op)))
   {
-    NdbEventOperationImpl* impl= &op->m_impl;
-    data.senderData = impl->m_oid;
-    insertDataL(impl, &data, ptr); 
+    // no need to lock()/unlock(), receive thread calls this
+    NdbEventOperationImpl* impl = &op->m_impl;
+    do if (!impl->m_node_bit_mask.isclear())
+    {
+      data.senderData = impl->m_oid;
+      insertDataL(impl, &data, ptr);
+    } while((impl = impl->m_next));
+    for (impl = m_dropped_ev_op; impl; impl = impl->m_next)
+      if (!impl->m_node_bit_mask.isclear())
+      {
+        data.senderData = impl->m_oid;
+        insertDataL(impl, &data, ptr);
+      }
   }
   DBUG_VOID_RETURN;
 }
@@ -1515,12 +1572,21 @@
   /**
    * Insert this event for each operation
    */
-  do
   {
-    NdbEventOperationImpl* impl= &op->m_impl;
-    data.senderData = impl->m_oid;
-    insertDataL(impl, &data, ptr);
-  } while((op = m_ndb->getEventOperation(op)));
+    // no need to lock()/unlock(), receive thread calls this
+    NdbEventOperationImpl* impl = &op->m_impl;
+    do if (!impl->m_node_bit_mask.isclear())
+    {
+      data.senderData = impl->m_oid;
+      insertDataL(impl, &data, ptr);
+    } while((impl = impl->m_next));
+    for (impl = m_dropped_ev_op; impl; impl = impl->m_next)
+      if (!impl->m_node_bit_mask.isclear())
+      {
+        data.senderData = impl->m_oid;
+        insertDataL(impl, &data, ptr);
+      }
+  }
   
   /**
    *  Release all GCI's with m_gci > gci
@@ -1565,7 +1631,11 @@
     }
   }
 
-  assert(bucket != 0);
+  if (bucket == 0)
+  {
+    // no bucket to complete
+    DBUG_VOID_RETURN;
+  }
 
   const Uint32 cnt= bucket->m_gcp_complete_rep_count = 1; 
   bucket->m_gci = gci;
@@ -1595,6 +1665,40 @@
 {
   DBUG_ENTER_EVENT("NdbEventBuffer::insertDataL");
   Uint64 gci= sdata->gci;
+  const bool is_data_event =
+    sdata->operation < NdbDictionary::Event::_TE_FIRST_NON_DATA_EVENT;
+
+  if (!is_data_event)
+  {
+    switch (sdata->operation)
+    {
+    case NdbDictionary::Event::_TE_NODE_FAILURE:
+      op->m_node_bit_mask.clear(sdata->ndbd_nodeid);
+      break;
+    case NdbDictionary::Event::_TE_ACTIVE:
+      op->m_node_bit_mask.set(sdata->ndbd_nodeid);
+      // internal event, do not relay to user
+      DBUG_RETURN_EVENT(0);
+      break;
+    case NdbDictionary::Event::_TE_CLUSTER_FAILURE:
+      op->m_node_bit_mask.clear();
+      DBUG_ASSERT(op->m_ref_count > 0);
+      op->m_ref_count--;
+      DBUG_PRINT("info", ("m_ref_count: %u for op: %p", op->m_ref_count, op));
+      break;
+    case NdbDictionary::Event::_TE_STOP:
+      op->m_node_bit_mask.clear(sdata->ndbd_nodeid);
+      if (op->m_node_bit_mask.isclear())
+      {
+        DBUG_ASSERT(op->m_ref_count > 0);
+        op->m_ref_count--;
+        DBUG_PRINT("info", ("m_ref_count: %u for op: %p", op->m_ref_count, op));
+      }
+      break;
+    default:
+      break;
+    }
+  }
 
   if ( likely((Uint32)op->mi_type & (1 << (Uint32)sdata->operation)) )
   {
@@ -1615,8 +1719,6 @@
     }
     
     const bool is_blob_event = (op->theMainOp != NULL);
-    const bool is_data_event =
-      sdata->operation < NdbDictionary::Event::_TE_FIRST_NON_DATA_EVENT;
     const bool use_hash =  op->m_mergeEvents && is_data_event;
 
     if (! is_data_event && is_blob_event)
@@ -2244,6 +2346,8 @@
 void
 EventBufData_list::add_gci_op(Gci_op g, bool del)
 {
+  DBUG_ENTER_EVENT("EventBufData_list::add_gci_op");
+  DBUG_PRINT_EVENT("info", ("p.op: %p  g.event_types: %x", g.op, g.event_types));
   assert(g.op != NULL);
   Uint32 i;
   for (i = 0; i < m_gci_op_count; i++) {
@@ -2273,8 +2377,15 @@
     }
     assert(m_gci_op_count < m_gci_op_alloc);
     assert(! del);
+#ifndef DBUG_OFF
+    i = m_gci_op_count;
+#endif
+    g.op->m_ref_count++;
+    DBUG_PRINT("info", ("m_ref_count: %u for op: %p", g.op->m_ref_count, g.op));
     m_gci_op_list[m_gci_op_count++] = g;
   }
+  DBUG_PRINT_EVENT("exit", ("m_gci_op_list[%u].event_types: %x", i,
m_gci_op_list[i].event_types));
+  DBUG_VOID_RETURN_EVENT;
 }
 
 void
@@ -2337,6 +2448,9 @@
     delete tOp;
     DBUG_RETURN(NULL);
   }
+  getEventOperationImpl(tOp)->m_ref_count = 1;
+  DBUG_PRINT("info", ("m_ref_count: %u for op: %p",
+                      getEventOperationImpl(tOp)->m_ref_count,
getEventOperationImpl(tOp)));
   DBUG_RETURN(tOp);
 }
 
@@ -2362,16 +2476,10 @@
 void
 NdbEventBuffer::dropEventOperation(NdbEventOperation* tOp)
 {
+  DBUG_ENTER("NdbEventBuffer::dropEventOperation");
   NdbEventOperationImpl* op= getEventOperationImpl(tOp);
 
   op->stop();
-
-  op->m_next= m_dropped_ev_op;
-  op->m_prev= 0;
-  if (m_dropped_ev_op)
-    m_dropped_ev_op->m_prev= op;
-  m_dropped_ev_op= op;
- 
   // stop blob event ops
   if (op->theMainOp == NULL)
   {
@@ -2391,11 +2499,25 @@
     }
   }
 
-  // ToDo, take care of these to be deleted at the
-  // appropriate time, after we are sure that there
-  // are _no_ more events coming
-
-  //  delete tOp;
+  DBUG_ASSERT(op->m_ref_count > 0);
+  op->m_ref_count--;
+  DBUG_PRINT("info", ("m_ref_count: %u for op: %p", op->m_ref_count, op));
+  if (op->m_ref_count == 0)
+  {
+    DBUG_PRINT("info", ("deleting op: %p", op));
+    DBUG_ASSERT(op->m_node_bit_mask.isclear());
+    ndbout_c("deleting NdbEventOperation %p", op->m_facade);
+    delete op->m_facade;
+  }
+  else
+  {
+    op->m_next= m_dropped_ev_op;
+    op->m_prev= 0;
+    if (m_dropped_ev_op)
+      m_dropped_ev_op->m_prev= op;
+    m_dropped_ev_op= op;
+  }
+  DBUG_VOID_RETURN;
 }
 
 void

--- 1.21/storage/ndb/src/ndbapi/NdbEventOperationImpl.hpp	2006-05-09 21:08:01 +02:00
+++ 1.22/storage/ndb/src/ndbapi/NdbEventOperationImpl.hpp	2006-05-18 23:37:53 +02:00
@@ -25,7 +25,7 @@
 #include <UtilBuffer.hpp>
 
 #define NDB_EVENT_OP_MAGIC_NUMBER 0xA9F301B4
-//#define EVENT_DEBUG
+#define EVENT_DEBUG
 #ifdef EVENT_DEBUG
 #define DBUG_ENTER_EVENT(A) DBUG_ENTER(A)
 #define DBUG_RETURN_EVENT(A) DBUG_RETURN(A)
@@ -367,6 +367,8 @@
   Uint32 m_eventId;
   Uint32 m_oid;
 
+  Bitmask<(unsigned int)_NDB_NODE_BITMASK_SIZE> m_node_bit_mask;
+  int m_ref_count;
   bool m_mergeEvents;
   
   EventBufData *m_data_item;
@@ -406,10 +408,10 @@
   void dropEventOperation(NdbEventOperation *);
   static NdbEventOperationImpl* getEventOperationImpl(NdbEventOperation* tOp);
 
-  void add_drop_lock();
-  void add_drop_unlock();
-  void lock();
-  void unlock();
+  void add_drop_lock() { NdbMutex_Lock(p_add_drop_mutex); }
+  void add_drop_unlock() { NdbMutex_Unlock(p_add_drop_mutex); }
+  void lock() { NdbMutex_Lock(m_mutex); }
+  void unlock() { NdbMutex_Unlock(m_mutex); }
 
   void add_op();
   void remove_op();
@@ -430,9 +432,11 @@
   Uint32 getEventId(int bufferId);
 
   int pollEvents(int aMillisecondNumber, Uint64 *latestGCI= 0);
+  int flushIncompleteEvents(Uint64 gci);
   NdbEventOperation *nextEvent();
   NdbEventOperationImpl* getGCIEventOperations(Uint32* iter,
                                                Uint32* event_types);
+  void NdbEventBuffer::deleteUsedEventOperations();
 
   NdbEventOperationImpl *move_data();
 

--- 1.4/mysql-test/r/ndb_autodiscover3.result	2006-05-17 08:34:41 +02:00
+++ 1.5/mysql-test/r/ndb_autodiscover3.result	2006-05-18 23:37:53 +02:00
@@ -18,6 +18,7 @@
 ERROR 42S02: Table 'test.t2' doesn't exist
 show tables like 't2';
 Tables_in_test (t2)
+reset master;
 create table t2 (a int key) engine=ndbcluster;
 insert into t2 values (1),(2),(3),(4),(5),(6),(7),(8),(9),(10);
 select * from t2 order by a limit 3;
@@ -30,10 +31,12 @@
 1
 2
 3
+reset master;
 select * from t2;
 ERROR 42S02: Table 'test.t2' doesn't exist
 show tables like 't2';
 Tables_in_test (t2)
+reset master;
 create table t2 (a int key) engine=ndbcluster;
 insert into t2 values (1),(2),(3),(4),(5),(6),(7),(8),(9),(10);
 select * from t2 order by a limit 3;
@@ -46,4 +49,5 @@
 1
 2
 3
+reset master;
 drop table t2;

--- 1.3/mysql-test/t/ndb_autodiscover3.test	2006-05-17 08:34:41 +02:00
+++ 1.4/mysql-test/t/ndb_autodiscover3.test	2006-05-18 23:37:53 +02:00
@@ -43,6 +43,7 @@
 --error ER_NO_SUCH_TABLE
 select * from t2;
 show tables like 't2';
+reset master;
 create table t2 (a int key) engine=ndbcluster;
 insert into t2 values (1),(2),(3),(4),(5),(6),(7),(8),(9),(10);
 select * from t2 order by a limit 3;
@@ -50,6 +51,7 @@
 # server 1 should have a stale cache, and in this case wrong frm, transaction must be
retried
 --connection server1
 select * from t2 order by a limit 3;
+reset master;
 
 --exec $NDB_MGM --no-defaults -e "all restart -i" >> $NDB_TOOLS_OUTPUT
 --exec $NDB_TOOLS_DIR/ndb_waiter --no-defaults >> $NDB_TOOLS_OUTPUT
@@ -60,6 +62,7 @@
 --error ER_NO_SUCH_TABLE
 select * from t2;
 show tables like 't2';
+reset master;
 create table t2 (a int key) engine=ndbcluster;
 insert into t2 values (1),(2),(3),(4),(5),(6),(7),(8),(9),(10);
 select * from t2 order by a limit 3;
@@ -67,6 +70,7 @@
 # server 2 should have a stale cache, but with right frm, transaction need not be retried
 --connection server2
 select * from t2 order by a limit 3;
+reset master;
 
 drop table t2;
 # End of 4.1 tests

--- 1.54/sql/ha_ndbcluster_binlog.cc	2006-05-17 08:34:41 +02:00
+++ 1.55/sql/ha_ndbcluster_binlog.cc	2006-05-18 23:37:53 +02:00
@@ -3321,6 +3321,9 @@
     DBUG_PRINT("info", ("schema_res: %d  schema_gci: %d", schema_res, schema_gci));
     if (schema_res > 0)
     {
+      i_ndb->pollEvents(0);
+      i_ndb->flushIncompleteEvents(schema_gci);
+      s_ndb->flushIncompleteEvents(schema_gci);
       if (schema_gci < ndb_latest_handled_binlog_epoch)
       {
         sql_print_error("NDB Binlog: cluster has been restarted --initial or with older
filesystem. "
Thread
bk commit into 5.1 tree (tomas:1.2154) BUG#17610tomas18 May