summaryrefslogtreecommitdiffstats
path: root/sql/rpl_tblmap.cc
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--sql/rpl_tblmap.cc182
1 files changed, 182 insertions, 0 deletions
diff --git a/sql/rpl_tblmap.cc b/sql/rpl_tblmap.cc
new file mode 100644
index 00000000..a230b9f6
--- /dev/null
+++ b/sql/rpl_tblmap.cc
@@ -0,0 +1,182 @@
+/* Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; version 2 of the License.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1335 USA */
+
+#include "mariadb.h"
+#include "sql_priv.h"
+
+#ifdef HAVE_REPLICATION
+
+#include "rpl_tblmap.h"
+#ifndef MYSQL_CLIENT
+#include "table.h"
+#endif
+
+#ifdef MYSQL_CLIENT
+#define MAYBE_TABLE_NAME(T) ("")
+#else
+#define MAYBE_TABLE_NAME(T) ((T) ? (T)->s->table_name.str : "<>")
+#endif
+#define TABLE_ID_HASH_SIZE 32
+#define TABLE_ID_CHUNK 256
+
+table_mapping::table_mapping()
+ : m_free(0)
+{
+#ifdef MYSQL_CLIENT
+ PSI_memory_key psi_key= PSI_NOT_INSTRUMENTED;
+#else
+ PSI_memory_key psi_key= key_memory_table_mapping_root;
+#endif
+
+ DBUG_ENTER("table_mapping::table_mapping");
+ /*
+ No "free_element" function for entries passed here, as the entries are
+ allocated in a MEM_ROOT (freed as a whole in the destructor), they cannot
+ be freed one by one.
+ Note that below we don't test if my_hash_init() succeeded. This
+ constructor is called at startup only.
+ */
+ (void) my_hash_init(psi_key, &m_table_ids,&my_charset_bin,TABLE_ID_HASH_SIZE,
+ offsetof(entry,table_id),sizeof(ulonglong),
+ 0,0,0);
+ /* We don't preallocate any block, this is consistent with m_free=0 above */
+ init_alloc_root(psi_key, &m_mem_root, TABLE_ID_HASH_SIZE*sizeof(entry), 0, MYF(0));
+ DBUG_VOID_RETURN;
+}
+
+table_mapping::~table_mapping()
+{
+#ifdef MYSQL_CLIENT
+ clear_tables();
+#endif
+ my_hash_free(&m_table_ids);
+ free_root(&m_mem_root, MYF(0));
+}
+
+TABLE* table_mapping::get_table(ulonglong table_id)
+{
+ DBUG_ENTER("table_mapping::get_table(ulong)");
+ DBUG_PRINT("enter", ("table_id: %llu", table_id));
+ entry *e= find_entry(table_id);
+ if (e)
+ {
+ DBUG_PRINT("info", ("tid %llu -> table %p (%s)",
+ table_id, e->table,
+ MAYBE_TABLE_NAME(e->table)));
+ DBUG_RETURN(e->table);
+ }
+
+ DBUG_PRINT("info", ("tid %llu is not mapped!", table_id));
+ DBUG_RETURN(NULL);
+}
+
+/*
+ Called when we are out of table id entries. Creates TABLE_ID_CHUNK
+ new entries, chain them and attach them at the head of the list of free
+ (free for use) entries.
+*/
+int table_mapping::expand()
+{
+ /*
+ If we wanted to use "tmp= new (&m_mem_root) entry[TABLE_ID_CHUNK]",
+ we would have to make "entry" derive from Sql_alloc but then it would not
+ be a POD anymore and we want it to be (see rpl_tblmap.h). So we allocate
+ in C.
+ */
+ entry *tmp= (entry *)alloc_root(&m_mem_root, TABLE_ID_CHUNK*sizeof(entry));
+ if (tmp == NULL)
+ return ERR_MEMORY_ALLOCATION; // Memory allocation failed
+
+ /* Find the end of this fresh new array of free entries */
+ entry *e_end= tmp+TABLE_ID_CHUNK-1;
+ for (entry *e= tmp; e < e_end; e++)
+ e->next= e+1;
+ e_end->next= m_free;
+ m_free= tmp;
+ return 0;
+}
+
+int table_mapping::set_table(ulonglong table_id, TABLE* table)
+{
+ DBUG_ENTER("table_mapping::set_table(ulong,TABLE*)");
+ DBUG_PRINT("enter", ("table_id: %llu table: %p (%s)",
+ table_id,
+ table, MAYBE_TABLE_NAME(table)));
+ entry *e= find_entry(table_id);
+ if (e == 0)
+ {
+ if (m_free == 0 && expand())
+ DBUG_RETURN(ERR_MEMORY_ALLOCATION); // Memory allocation failed
+ e= m_free;
+ m_free= m_free->next;
+ }
+ else
+ {
+#ifdef MYSQL_CLIENT
+ free_table_map_log_event(e->table);
+#endif
+ my_hash_delete(&m_table_ids,(uchar *)e);
+ }
+ e->table_id= table_id;
+ e->table= table;
+ if (my_hash_insert(&m_table_ids,(uchar *)e))
+ {
+ /* we add this entry to the chain of free (free for use) entries */
+ e->next= m_free;
+ m_free= e;
+ DBUG_RETURN(ERR_MEMORY_ALLOCATION);
+ }
+
+ DBUG_PRINT("info", ("tid %llu -> table %p (%s)",
+ table_id, e->table,
+ MAYBE_TABLE_NAME(e->table)));
+ DBUG_RETURN(0); // All OK
+}
+
+int table_mapping::remove_table(ulonglong table_id)
+{
+ entry *e= find_entry(table_id);
+ if (e)
+ {
+ my_hash_delete(&m_table_ids,(uchar *)e);
+ /* we add this entry to the chain of free (free for use) entries */
+ e->next= m_free;
+ m_free= e;
+ return 0; // All OK
+ }
+ return 1; // No table to remove
+}
+
+/*
+ Puts all entries into the list of free-for-use entries (does not free any
+ memory), and empties the hash.
+*/
+void table_mapping::clear_tables()
+{
+ DBUG_ENTER("table_mapping::clear_tables()");
+ for (uint i= 0; i < m_table_ids.records; i++)
+ {
+ entry *e= (entry *)my_hash_element(&m_table_ids, i);
+#ifdef MYSQL_CLIENT
+ free_table_map_log_event(e->table);
+#endif
+ e->next= m_free;
+ m_free= e;
+ }
+ my_hash_reset(&m_table_ids);
+ DBUG_VOID_RETURN;
+}
+
+#endif