diff options
Diffstat (limited to 'sql/rpl_tblmap.cc')
-rw-r--r-- | sql/rpl_tblmap.cc | 151 |
1 files changed, 151 insertions, 0 deletions
diff --git a/sql/rpl_tblmap.cc b/sql/rpl_tblmap.cc new file mode 100644 index 00000000000..a0272b23ee8 --- /dev/null +++ b/sql/rpl_tblmap.cc @@ -0,0 +1,151 @@ +/* Copyright (C) 2005 MySQL AB + + 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; either version 2 of the License, or + (at your option) any later version. + + 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ + +#include "mysql_priv.h" + +#ifdef HAVE_REPLICATION + +#include "rpl_tblmap.h" + +#define MAYBE_TABLE_NAME(T) ((T) ? (T)->s->table_name.str : "<>") +#define TABLE_ID_HASH_SIZE 32 +#define TABLE_ID_CHUNK 256 + +table_mapping::table_mapping() + : m_free(0) +{ + /* + 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 hash_init() succeeded. This constructor + is called at startup only. + */ + (void) hash_init(&m_table_ids,&my_charset_bin,TABLE_ID_HASH_SIZE, + offsetof(entry,table_id),sizeof(ulong), + 0,0,0); + /* We don't preallocate any block, this is consistent with m_free=0 above */ + init_alloc_root(&m_mem_root, TABLE_ID_HASH_SIZE*sizeof(entry), 0); +} + +table_mapping::~table_mapping() +{ + hash_free(&m_table_ids); + free_root(&m_mem_root, MYF(0)); +} + +st_table* table_mapping::get_table(ulong table_id) +{ + DBUG_ENTER("table_mapping::get_table(ulong)"); + DBUG_PRINT("enter", ("table_id=%d", table_id)); + entry *e= find_entry(table_id); + if (e) + { + DBUG_PRINT("info", ("tid %d -> table %p (%s)", + 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); +} + +/* + 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(ulong table_id, TABLE* table) +{ + DBUG_ENTER("table_mapping::set_table(ulong,TABLE*)"); + DBUG_PRINT("enter", ("table_id=%d, 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 + hash_delete(&m_table_ids,(byte *)e); + + 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, e->table, + MAYBE_TABLE_NAME(e->table))); + DBUG_RETURN(0); // All OK +} + +int table_mapping::remove_table(ulong table_id) +{ + entry *e= find_entry(table_id); + if (e) + { + hash_delete(&m_table_ids,(byte *)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 *)hash_element(&m_table_ids, i); + e->next= m_free; + m_free= e; + } + my_hash_reset(&m_table_ids); + DBUG_VOID_RETURN; +} + +#endif |