List:Internals« Previous MessageNext Message »
From:tomas Date:May 24 2005 12:03pm
Subject:bk commit into 5.1 tree (tomas:1.1871)
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.1871 05/05/24 12:03:33 tomas@stripped +7 -0
      removed usage of table map in mysql bin log
      added table_map_id on table object instead
     changed table mapping to only be id->TABLE*
      changed table mapping to use hash insead of linear search

  sql/table.h
    1.99 05/05/24 12:03:27 tomas@stripped +3 -0
    removed usage of table map in mysql bin log
    added table_map_id on table object instead

  sql/table.cc
    1.163 05/05/24 12:03:26 tomas@stripped +4 -0
    removed usage of table map in mysql bin log
    added table_map_id on table object instead

  sql/sql_class.h
    1.241 05/05/24 12:03:26 tomas@stripped +17 -10
    removed usage of table map in mysql bin log
    added table_map_id on table object instead

  sql/sql_class.cc
    1.188 05/05/24 12:03:26 tomas@stripped +19 -12
    removed usage of table map in mysql bin log
    added table_map_id on table object instead

  sql/rpl_tblmap.h
    1.5 05/05/24 12:03:26 tomas@stripped +19 -31
    changed table mapping to only be id->TABLE*
    changed table mapping to use hash insead of linear search

  sql/rpl_tblmap.cc
    1.7 05/05/24 12:03:26 tomas@stripped +75 -104
    changed table mapping to only be id->TABLE*
    changed table mapping to use hash insead of linear search

  sql/log.cc
    1.168 05/05/24 12:03:26 tomas@stripped +15 -35
    removed usage of table map in mysql bin log
    added table_map_id on table object instead

# 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/wl2325-test

--- 1.167/sql/log.cc	2005-05-09 23:17:23 +02:00
+++ 1.168/sql/log.cc	2005-05-24 12:03:26 +02:00
@@ -349,7 +349,7 @@
   :bytes_written(0), last_time(0), query_start(0), name(0),
    file_id(1), open_count(1), log_type(LOG_CLOSED), write_error(0), inited(0),
    need_start_event(1), prepared_xids(0), 
-   m_table_map(NULL), m_next_table_id(0), 
+   m_next_table_id(0), 
    description_event_for_exec(0), description_event_for_queue(0)
 {
   /*
@@ -377,6 +377,7 @@
     (void) pthread_mutex_destroy(&LOCK_log);
     (void) pthread_mutex_destroy(&LOCK_index);
     (void) pthread_cond_destroy(&update_cond);
+    (void) pthread_mutex_destroy(&LOCK_next_table_id);
   }
   DBUG_VOID_RETURN;
 }
@@ -423,6 +424,7 @@
   (void) pthread_mutex_init(&LOCK_log,MY_MUTEX_INIT_SLOW);
   (void) pthread_mutex_init(&LOCK_index, MY_MUTEX_INIT_SLOW);
   (void) pthread_cond_init(&update_cond, 0);
+  (void) pthread_mutex_init(&LOCK_next_table_id, MY_MUTEX_INIT_FAST);
 }
 
 const char *MYSQL_LOG::generate_name(const char *log_name,
@@ -2277,49 +2279,27 @@
   DBUG_ENTER("MYSQL_LOG::get_table_id(TABLE*)");
   DBUG_PRINT("enter", ("table=%p", table)); 
   DBUG_ASSERT(table != NULL);
-
-  // Have to create it here since it relies on my_malloc, which requires
-  // my_init() to have been executed prior to this.
-  if (m_table_map == NULL)
-    m_table_map = new table_mapping;
-
-  DBUG_ASSERT(m_table_map != NULL);
-
-  ulong tid = m_table_map->get_table_id(table);
+  ulong tid= table->s->table_map_id;
   if (tid == table_mapping::NO_TABLE) {
-    // We can't use the number of tables in the list since the highest table
-    // id might be larger than the number of elements in the list. 
+    pthread_mutex_lock(&LOCK_next_table_id);
+    // need to double check under mutex that no other thread has snuck in
+    // and set the table_map_id
+    if ((tid= table->s->table_map_id) != table_mapping::NO_TABLE)
+      goto get_table_id_set;
+
+    // get next id
     tid = m_next_table_id++;
 
     // There is one reserved number that cannot be used.
     if (tid == table_mapping::NO_TABLE)
 	tid = m_next_table_id++;
-	
-    m_table_map->set_table(tid, table);
+
+    table->s->table_map_id= tid;
+get_table_id_set:
+    pthread_mutex_unlock(&LOCK_next_table_id);
   }
   DBUG_PRINT("return", ("table_id=%d", tid));
   DBUG_RETURN(tid);
-}
-
-int MYSQL_LOG::
-is_table_mapped(TABLE* table) const
-{
-  DBUG_ASSERT(table != NULL);
-
-  // Have to create it here since it relies on my_malloc, which requires
-  // my_init() to have been executed prior to this.
-  if (m_table_map == NULL)
-    m_table_map = new table_mapping;
-
-  DBUG_ASSERT(m_table_map != NULL);
-  return m_table_map->get_table_id(table) != table_mapping::NO_TABLE;
-}
-
-void MYSQL_LOG::
-clear_table_mappings()
-{
-  DBUG_ASSERT(m_table_map != NULL);
-  m_table_map->clear_tables();
 }
 
 #endif // !defined(MYSQL_CLIENT) && defined(HAVE_REPLICATION)

--- 1.187/sql/sql_class.cc	2005-05-20 16:20:02 +02:00
+++ 1.188/sql/sql_class.cc	2005-05-24 12:03:26 +02:00
@@ -210,7 +210,7 @@
   ull=0;
   system_thread= cleanup_done= abort_on_warning= no_warnings_for_error= 0;
   peer_port= 0;					// For SHOW PROCESSLIST
-  transaction.m_pending_rows_event = 0;
+  transaction.m_pending_rows_event= 0;
 #ifdef	__WIN__
   real_id = 0;
 #endif
@@ -1836,7 +1836,7 @@
 set_pending_event(Rows_log_event* ev) 
 {
   DBUG_ENTER("THD::set_pending_event(Rows_log_event*)");
-  transaction.m_pending_rows_event = ev;
+  transaction.m_pending_rows_event= ev;
   DBUG_RETURN(0);		// Ok
 }
 
@@ -1844,7 +1844,7 @@
 get_pending_event() const 
 {
   DBUG_ENTER("THD::get_pending_event()");
-  Rows_log_event* ev = transaction.m_pending_rows_event;
+  Rows_log_event* ev= transaction.m_pending_rows_event;
   DBUG_RETURN(ev);
 }
 
@@ -1873,13 +1873,13 @@
 		bool is_transactional) 
 {
   // Fetch the type code for the RowsEventT template parameter
-  int const type_code = RowsEventT::TYPE_CODE;
+  int const type_code= RowsEventT::TYPE_CODE;
   DBUG_ENTER("THD::prepare_pending<RowsEventT>(TABLE*, ...)");
   DBUG_PRINT("enter", ("table=%p (%s), type_code=%d, needed=%d", 
 		       table, table->s->table_name,
 		       type_code, needed));
 
-  Rows_log_event* pending = get_pending_event();
+  Rows_log_event* pending= get_pending_event();
 
   if (pending) 
   {
@@ -1899,16 +1899,17 @@
   // Check if the current event is non-NULL and a write-rows event. Also check
   // if the table provided is mapped: if it is not, then we have switched to
   // writing to a new table.
-  bool was_mapped = false;
+  bool was_mapped= false;
+//      || pending->m_table != table
   if (!pending
       || pending->server_id != server_id
       || pending->get_type_code() != type_code
       || pending->get_data_size() + needed > opt_binlog_rows_event_max_size
       || pending->get_cols() != cols
-      || !(was_mapped= mysql_bin_log.is_table_mapped(table))) 
+      || !(was_mapped= is_table_mapped(table)))
   {
     // If not, flush the event and create a new RowsEventT.
-    ulong const tid = mysql_bin_log.get_table_id(table);
+    ulong const tid= get_table_id(table);
 
     Rows_log_event* const 
 	ev = new RowsEventT(this, table, tid, cols, is_transactional);
@@ -1955,7 +1956,7 @@
   DBUG_ASSERT(opt_binlog_row_level);
   DBUG_ASSERT(mysql_bin_log.is_open());
   
-  if (Rows_log_event* pending = get_pending_event()) {
+  if (Rows_log_event* pending= get_pending_event()) {
     if (mysql_bin_log.write(pending)) {
       DBUG_PRINT("exit", ("1"));
       DBUG_RETURN(1);		// Something failed
@@ -2264,6 +2265,13 @@
   DBUG_RETURN(error);
 }
 
+ulong THD::
+get_new_table_id(TABLE* table)
+{
+  ulong id= mysql_bin_log.get_table_id(table);
+  return id;
+}
+
 int THD::
 write_table_map(TABLE* table, bool is_transactional)
 {
@@ -2273,7 +2281,7 @@
   if (!opt_binlog_row_level || !mysql_bin_log.is_open())
     DBUG_RETURN(0);
 
-  ulong table_id = mysql_bin_log.get_table_id(table);
+  ulong table_id= get_table_id(table);
 
   Table_map_log_event::enum_flags const
     flags = Table_map_log_event::NO_FLAGS;
@@ -2299,11 +2307,10 @@
     set. 
   */
   if (trans_end) {
-    if (Rows_log_event* pending = get_pending_event()) {
+    if (Rows_log_event* pending= get_pending_event()) {
       pending->set_flag(Rows_log_event::TRANS_END_F);
 
       DBUG_ASSERT(mysql_bin_log.is_open());
-      mysql_bin_log.clear_table_mappings();
     }
   }
   

--- 1.240/sql/sql_class.h	2005-05-09 23:17:25 +02:00
+++ 1.241/sql/sql_class.h	2005-05-24 12:03:26 +02:00
@@ -240,9 +240,7 @@
   pthread_cond_t  COND_prep_xids;
   friend class Log_event;
 
-  // 'Mutable' needed since this class can not be initialized in the
-  // constructor.  
-  mutable table_mapping* m_table_map;
+  pthread_mutex_t LOCK_next_table_id;
   ulong m_next_table_id;
 
 public:
@@ -263,13 +261,6 @@
   // This will return a table id for the table. If the table is not known, a
   // new table id will be invented and returned. 
   ulong get_table_id(TABLE* table);
-
-  // This will check if the given table is mapped to any table id
-  int is_table_mapped(TABLE* table) const;
-
-  // This will clear all table mappings
-  void clear_table_mappings();
-
 #endif // !defined(MYSQL_CLIENT) && defined(HAVE_REPLICATION)
   /*
      These describe the log's format. This is used only for relay logs.
@@ -1117,6 +1108,22 @@
 		  byte *row_data, size_t max_len, const byte *data) const;
 
   int flush_pending_event(bool transaction_end);
+
+  ulong get_new_table_id(TABLE* table);
+
+  ulong get_table_id(TABLE* table)
+  {
+    ulong id= table->s->table_map_id;
+    if (id != table_mapping::NO_TABLE)
+      return id;
+    return get_new_table_id(table);
+  }
+
+  int is_table_mapped(TABLE* table)
+  {
+    return table->s->table_map_id != table_mapping::NO_TABLE;
+  }
+
   int write_table_map(TABLE*,bool);
 #endif
 

--- 1.162/sql/table.cc	2005-05-10 00:58:28 +02:00
+++ 1.163/sql/table.cc	2005-05-24 12:03:26 +02:00
@@ -848,6 +848,10 @@
   if (use_hash)
     (void) hash_check(&share->name_hash);
 #endif
+#ifdef HAVE_REPLICATION
+  share->table_map_id= table_mapping::NO_TABLE;
+#endif
+
   DBUG_RETURN (0);
 
  err:

--- 1.98/sql/table.h	2005-05-09 14:26:50 +02:00
+++ 1.99/sql/table.h	2005-05-24 12:03:27 +02:00
@@ -163,6 +163,9 @@
   my_bool crashed;
   my_bool is_view;
   my_bool name_lock, replace_with_name_lock;
+#ifdef HAVE_REPLICATION
+  ulong table_map_id;
+#endif
 } TABLE_SHARE;
 
 

--- 1.6/sql/rpl_tblmap.cc	2005-05-07 15:11:30 +02:00
+++ 1.7/sql/rpl_tblmap.cc	2005-05-24 12:03:26 +02:00
@@ -4,158 +4,123 @@
 #include "my_pthread.h"
 
 #define MAYBE_TABLE_NAME(T) ((T) ? (T)->s->table_name : "<>")
+#define TABLE_ID_HASH_SIZE 32
+#define TABLE_ID_CHUNK 256
 
 table_mapping::
 table_mapping()
-  : m_array(0), m_count(0), m_reserve(16)
+  : m_array(0), m_free(0), m_reserve(0)
 {
-  pthread_mutex_init(&m_mutex, NULL);
-  sentry sentry(&m_mutex);
-
-  // TODO: my_malloc() can fail
-  m_array = reinterpret_cast<entry*>(my_malloc(m_reserve * sizeof(*m_array), 
-					       MYF(0)));
+  (void) hash_init(&m_table_ids,&my_charset_bin,TABLE_ID_HASH_SIZE,
+		   offsetof(entry,table_id),sizeof(ulong),
+		   0,0,0);
 }
 
 table_mapping::
 ~table_mapping()
 {
   {
-    sentry sentry(&m_mutex);
+    for (int i= 0; i < m_reserve; i++)
+      my_free(reinterpret_cast<char*>(m_array[i]), MYF(MY_ALLOW_ZERO_PTR));
     my_free(reinterpret_cast<char*>(m_array), MYF(MY_ALLOW_ZERO_PTR));
     m_array = NULL;
   }
-  pthread_mutex_destroy(&m_mutex);
-}
-
-ulong table_mapping::
-find_pos(ulong table_id) const
-{
-  DBUG_ASSERT(m_count <= m_reserve);
-  DBUG_ASSERT(m_array != NULL);
-  // N.B.: This is a linear search, it will be infeasible to use for larger
-  // number of tables in the air at the same time. Switch to a binary search
-  // later.
-  for (ulong i = 0 ; i < m_count ; ++i) {
-    if (m_array[i].table_id == table_id)
-      return i;
-  }
-  return m_count;
-}
-
-ulong table_mapping::
-find_pos(st_table* table) const
-{
-  DBUG_ASSERT(m_count <= m_reserve);
-  DBUG_ASSERT(m_array != NULL);
-  // N.B.: This is a linear search, it will be infeasible to use for larger
-  // number of tables in the air at the same time. Switch to a binary search
-  // later.
-  for (ulong i = 0 ; i < m_count ; ++i) {
-    if (m_array[i].table == table)
-      return i;
-  }
-  return m_count;
 }
 
 st_table* table_mapping::
 get_table(ulong table_id)
 {
-  sentry sentry(&m_mutex);	// Acquire exlusive access
-
   DBUG_ENTER("table_mapping::get_table(ulong)");
   DBUG_PRINT("enter", ("table_id=%d", table_id));
-  pos_type const pos = find_pos(table_id);
-  if (pos < m_count) 
+  entry *e= find_entry(table_id);
+  if (e) 
   {
     DBUG_PRINT("info", ("tid %d -> table %p (%s)", 
-			table_id, m_array[pos].table,
-			MAYBE_TABLE_NAME(m_array[pos].table)));
-    DBUG_RETURN(m_array[pos].table);
+			table_id, e->table,
+			MAYBE_TABLE_NAME(e->table)));
+    DBUG_RETURN(e->table);
   }
 
   DBUG_PRINT("info", ("tid %d is not mapped!", table_id));
   DBUG_RETURN(NULL);
 }
 
-
-ulong table_mapping::
-get_table_id(st_table* table)
+int table_mapping::
+expand()
 {
-  sentry sentry(&m_mutex);	// Aquire exclusive access
-
-  DBUG_ENTER("table_mapping::get_table_id(st_table*)");
-  DBUG_PRINT("enter", ("table=%p (%s)", table, MAYBE_TABLE_NAME(table)));
-  pos_type const pos = find_pos(table);
-  if (pos < m_count)
-  {
-    DBUG_PRINT("info", ("table %p (%s) -> table id %d", 
-			m_array[pos].table,
-			MAYBE_TABLE_NAME(m_array[pos].table),
-			m_array[pos].table_id));
-    DBUG_RETURN(m_array[pos].table_id);
-  }
-  DBUG_PRINT("info", ("table %p (%s) is not mapped!", 
-		      table, 
-		      MAYBE_TABLE_NAME(table)));
-  DBUG_RETURN(NO_TABLE);
+  int reserve= m_reserve+1;
+  {
+    entry **array;
+    if (m_array)
+      array= (entry **)my_realloc((char*) m_array, 
+				  reserve*sizeof(*m_array), 
+				  MYF(MY_WME));
+    else
+      array= (entry **)my_malloc(reserve*sizeof(*m_array), 
+				 MYF(MY_WME));
+    if (array == NULL)
+    {
+      return ERR_MEMORY_ALLOCATION; // Memory allocation failed
+    }
+    m_array = array;
+  }
+  {
+    entry *tmp= (entry *)my_malloc(TABLE_ID_CHUNK*sizeof(**m_array),MYF(MY_WME));
+    if (tmp == NULL)
+    {
+      return ERR_MEMORY_ALLOCATION; // Memory allocation failed
+    }
+    m_array[m_reserve]= tmp;
+    
+    entry *e_end= tmp+TABLE_ID_CHUNK-1;
+    for (entry *e= tmp; e < e_end; e++)
+      e->next= e;
+    e_end->next= m_free;
+    m_free= tmp;
+  }
+  m_reserve= reserve;
+  return 0;
 }
 
 int table_mapping::
 set_table(ulong table_id, TABLE* table)
 {
-  sentry sentry(&m_mutex);
-
   DBUG_ENTER("table_mapping::set_table(ulong,TABLE*)");
   DBUG_PRINT("enter", ("table_id=%d, table=%p (%s)", 
 		       table_id, 
 		       table, MAYBE_TABLE_NAME(table)));
-  pos_type const pos = find_pos(table_id);
-
-  if (pos == m_count && m_reserve == m_count) 
+  entry *e= find_entry(table_id);
+  if (e == 0)
   {
-    // We're adding a new table now, we need to extend the array to make space
-    // for the new table data.
-    if (m_reserve > ULONG_MAX/2)
-      DBUG_RETURN(ERR_LIMIT_EXCEEDED); // Table upper limit exceeded
-
-    int const reserve = 2*m_reserve;
-    entry* const 
-      array = (entry*) my_realloc((char*) m_array, 
-				  reserve*sizeof(*m_array), 
-				  MYF(MY_WME));
-    if (array == NULL)
-    {
-      DBUG_RETURN(ERR_MEMORY_ALLOCATION); // Memory allocation failed
-    }
-    m_reserve = reserve;
-    m_array = array;
+    if (m_free == 0 && expand())
+      DBUG_RETURN(ERR_MEMORY_ALLOCATION); // Memory allocation failed      
+    e= m_free;
+    m_free= m_free->next;
+  }
+  else
+  {
+    hash_delete(&m_table_ids,(byte *)e);
   }
 
-  DBUG_ASSERT(m_count <= m_reserve);
-  if (pos == m_count)
-    ++m_count;
-
-  DBUG_ASSERT(pos < m_count);
-  m_array[pos].table_id = table_id;
-  m_array[pos].table = table;
+  e->table_id= table_id;
+  e->table= table;
+  my_hash_insert(&m_table_ids,(byte *)e);
+
   DBUG_PRINT("info", ("tid %d -> table %p (%s)", 
-		      table_id, m_array[pos].table,
-		      MAYBE_TABLE_NAME(m_array[pos].table)));
+		      table_id, e->table,
+		      MAYBE_TABLE_NAME(e->table)));
   DBUG_RETURN(0);		// All OK
 }
 
 int table_mapping::
 remove_table(ulong table_id)
 {
-  sentry sentry(&m_mutex);
-
-  ulong pos = find_pos(table_id);
-  if (pos < m_count)
+  entry *e= find_entry(table_id);
+  if (e)
   {
-    while (++pos < m_count)
-      m_array[pos-1] = m_array[pos];
-    --m_count;
+    hash_delete(&m_table_ids,(byte *)e);
+    e->next= m_free;
+    m_free= e;
     return 0;			// All OK
   }
   return 1;			// No table to remove
@@ -165,7 +130,13 @@
 clear_tables()
 {
   DBUG_ENTER("table_mapping::clear_tables()");
-  m_count = 0;
+  for (uint i= 0; i < m_table_ids.records; i++)
+  {
+    entry *e= (entry *)hash_element(&m_table_ids, i);
+    e->next= m_free;
+    m_free= e;
+  }
+  my_hash_reset(&m_table_ids);
   DBUG_VOID_RETURN;
 }
 

--- 1.4/sql/rpl_tblmap.h	2005-05-04 15:59:53 +02:00
+++ 1.5/sql/rpl_tblmap.h	2005-05-24 12:03:26 +02:00
@@ -13,16 +13,13 @@
   CLASS table_mapping
 
   RESPONSIBILITIES
-    The table mapping is used to map table pointer to table id's and vice
-    versa.
+    The table mapping is used to map table id's to table pointers
 
   COLLABORATION
-    MYSQL_LOG    For mapping tables to table id:s before sending events.
     RELAY_LOG    For mapping table id:s to tables when receiving events.
  */
 class table_mapping {
 public:
-  typedef ulong pos_type;
 
   enum {
     NO_TABLE = ULONG_MAX
@@ -39,42 +36,33 @@
 
   TABLE* get_table(ulong table_id);
 
-  /*
-    Return table id for 'table', or NO_TABLE if there is no id mapped for
-    table.
-  */
-  ulong     get_table_id(TABLE* table);
-
   int       set_table(ulong table_id, TABLE* table);
   int       remove_table(ulong table_id);
   void      clear_tables();
-  ulong     count() const { return m_count; }
+  ulong     count() const { return m_table_ids.records; }
 
 private:
-  pos_type  find_pos(ulong table_id) const;
-  pos_type  find_pos(TABLE* table) const;
-
   struct entry { 
-      ulong table_id; 
-      TABLE* table; 
+    ulong table_id;
+    union {
+      TABLE *table;
+      entry *next;
+    };
   };
-  entry *m_array;
-  ulong m_count, m_reserve;
 
-  class sentry {
-  public:
-    sentry(pthread_mutex_t *mutex) 
-      : m_mptr(mutex) 
-    { 
-      pthread_mutex_lock(m_mptr); 
-    }
-
-    ~sentry() { pthread_mutex_unlock(m_mptr); }
-  private:
-    pthread_mutex_t* m_mptr;
-  };
+  entry *find_entry(ulong table_id)
+  {
+    return (entry *)hash_search(&m_table_ids,
+				(byte*)&table_id,
+				sizeof(table_id));
+  }
+  int expand();
+
+  entry **m_array;
+  entry *m_free;
+  ulong m_reserve;
 
-  pthread_mutex_t m_mutex;
+  HASH m_table_ids;
 };
 
 #endif
Thread
bk commit into 5.1 tree (tomas:1.1871)tomas24 May