diff options
author | Jon Olav Hauglid <jon.hauglid@sun.com> | 2010-07-01 15:53:46 +0200 |
---|---|---|
committer | Jon Olav Hauglid <jon.hauglid@sun.com> | 2010-07-01 15:53:46 +0200 |
commit | 9ff272fbbd9f8e8bb412cf8ddc12d6e97242ef63 (patch) | |
tree | c9d08724cb81d3b7ffd2f6515930d6df9e4b5bf1 /sql/sql_hset.h | |
parent | 29e9130d60d79b88b9e6593a111ced4363e9225e (diff) | |
download | mariadb-git-9ff272fbbd9f8e8bb412cf8ddc12d6e97242ef63.tar.gz |
A 5.5 version of the fix for Bug #54360 "Deadlock DROP/ALTER/CREATE
DATABASE with open HANDLER"
Remove LOCK_create_db, database name locks, and use metadata locks instead.
This exposes CREATE/DROP/ALTER DATABASE statements to the graph-based
deadlock detector in MDL, and paves the way for a safe, deadlock-free
implementation of RENAME DATABASE.
Database DDL statements will now take exclusive metadata locks on
the database name, while table/view/routine DDL statements take
intention exclusive locks on the database name. This prevents race
conditions between database DDL and table/view/routine DDL.
(e.g. DROP DATABASE with concurrent CREATE/ALTER/DROP TABLE)
By adding database name locks, this patch implements
WL#4450 "DDL locking: CREATE/DROP DATABASE must use database locks" and
WL#4985 "DDL locking: namespace/hierarchical locks".
The patch also changes code to use init_one_table() where appropriate.
The new lock_table_names() function requires TABLE_LIST::db_length to
be set correctly, and this is taken care of by init_one_table().
This patch also adds a simple template to help work with
the mysys HASH data structure.
Most of the patch was written by Konstantin Osipov.
Diffstat (limited to 'sql/sql_hset.h')
-rw-r--r-- | sql/sql_hset.h | 117 |
1 files changed, 117 insertions, 0 deletions
diff --git a/sql/sql_hset.h b/sql/sql_hset.h new file mode 100644 index 00000000000..c3b98b881f5 --- /dev/null +++ b/sql/sql_hset.h @@ -0,0 +1,117 @@ +#ifndef SQL_HSET_INCLUDED +#define SQL_HSET_INCLUDED +/* Copyright (c) 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ + +#include "my_global.h" +#include "hash.h" + + +/** + A type-safe wrapper around mysys HASH. +*/ + +template <typename T, my_hash_get_key K> +class Hash_set +{ +public: + typedef T Value_type; + enum { START_SIZE= 8 }; + /** + Constructs an empty hash. Does not allocate memory, it is done upon + the first insert. Thus does not cause or return errors. + */ + Hash_set(); + /** + Destroy the hash by freeing the buckets table. Does + not call destructors for the elements. + */ + ~Hash_set(); + /** + Insert a single value into a hash. Does not tell whether + the value was inserted -- if an identical value existed, + it is not replaced. + + @retval TRUE Out of memory. + @retval FALSE OK. The value either was inserted or existed + in the hash. + */ + bool insert(T *value); + /** Is this hash set empty? */ + bool is_empty() const { return m_hash.records == 0; } + /** Returns the number of unique elements. */ + size_t size() const { return static_cast<size_t>(m_hash.records); } + /** An iterator over hash elements. Is not insert-stable. */ + class Iterator + { + public: + Iterator(Hash_set &hash_set); + /** + Return the current element and reposition the iterator to the next + element. + */ + inline T *operator++(int); + void rewind() { m_idx= 0; } + private: + HASH *m_hash; + uint m_idx; + }; +private: + HASH m_hash; +}; + + +template <typename T, my_hash_get_key K> +Hash_set<T, K>::Hash_set() +{ + my_hash_clear(&m_hash); +} + + +template <typename T, my_hash_get_key K> +Hash_set<T, K>::~Hash_set() +{ + my_hash_free(&m_hash); +} + + +template <typename T, my_hash_get_key K> +bool Hash_set<T, K>::insert(T *value) +{ + my_hash_init_opt(&m_hash, &my_charset_bin, START_SIZE, 0, 0, K, 0, MYF(0)); + size_t key_len; + const uchar *key= K(reinterpret_cast<uchar*>(value), &key_len, FALSE); + if (my_hash_search(&m_hash, key, key_len) == NULL) + return my_hash_insert(&m_hash, reinterpret_cast<uchar *>(value)); + return FALSE; +} + + +template <typename T, my_hash_get_key K> +Hash_set<T, K>::Iterator::Iterator(Hash_set<T, K> &set_arg) + :m_hash(&set_arg.m_hash), + m_idx(0) +{} + + +template <typename T, my_hash_get_key K> +inline T *Hash_set<T, K>::Iterator::operator++(int) +{ + if (m_idx < m_hash->records) + return reinterpret_cast<T*>(my_hash_element(m_hash, m_idx++)); + return NULL; +} + +#endif // SQL_HSET_INCLUDED |