mirror of
https://github.com/MariaDB/server.git
synced 2025-01-15 19:42:28 +01:00
182 lines
5 KiB
C++
182 lines
5 KiB
C++
/* 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
|