mirror of
https://github.com/MariaDB/server.git
synced 2025-07-27 18:02:13 +03:00
Patch that changes metadata locking subsystem to use mutex per lock and
condition variable per context instead of one mutex and one conditional variable for the whole subsystem. This should increase concurrency in this subsystem. It also opens the way for further changes which are necessary to solve such bugs as bug #46272 "MySQL 5.4.4, new MDL: unnecessary deadlock" and bug #37346 "innodb does not detect deadlock between update and alter table". Two other notable changes done by this patch: - MDL subsystem no longer implicitly acquires global intention exclusive metadata lock when per-object metadata lock is acquired. Now this has to be done by explicit calls outside of MDL subsystem. - Instead of using separate MDL_context for opening system tables/tables for purposes of I_S we now create MDL savepoint in the main context before opening tables and rollback to this savepoint after closing them. This means that it is now possible to get ER_LOCK_DEADLOCK error even not inside a transaction. This might happen in unlikely case when one runs DDL on one of system tables while also running DDL on some other tables. Cases when this ER_LOCK_DEADLOCK error is not justified will be addressed by advanced deadlock detector for MDL subsystem which we plan to implement.
This commit is contained in:
@ -18,7 +18,8 @@
|
||||
|
||||
#include <my_global.h>
|
||||
|
||||
template <typename T, typename B> class I_P_List_iterator;
|
||||
template <typename T, typename B, typename C> class I_P_List_iterator;
|
||||
class I_P_List_null_counter;
|
||||
|
||||
|
||||
/**
|
||||
@ -47,10 +48,14 @@ template <typename T, typename B> class I_P_List_iterator;
|
||||
return &el->prev;
|
||||
}
|
||||
};
|
||||
@param C Policy class specifying how counting of elements in the list
|
||||
should be done. Instance of this class is also used as a place
|
||||
where information about number of list elements is stored.
|
||||
@sa I_P_List_null_counter, I_P_List_counter
|
||||
*/
|
||||
|
||||
template <typename T, typename B>
|
||||
class I_P_List
|
||||
template <typename T, typename B, typename C = I_P_List_null_counter>
|
||||
class I_P_List : public C
|
||||
{
|
||||
T *first;
|
||||
|
||||
@ -61,7 +66,7 @@ class I_P_List
|
||||
*/
|
||||
public:
|
||||
I_P_List() : first(NULL) { };
|
||||
inline void empty() { first= NULL; }
|
||||
inline void empty() { first= NULL; C::reset(); }
|
||||
inline bool is_empty() const { return (first == NULL); }
|
||||
inline void push_front(T* a)
|
||||
{
|
||||
@ -70,6 +75,7 @@ public:
|
||||
*B::prev_ptr(first)= B::next_ptr(a);
|
||||
first= a;
|
||||
*B::prev_ptr(a)= &first;
|
||||
C::inc();
|
||||
}
|
||||
inline void push_back(T *a)
|
||||
{
|
||||
@ -107,21 +113,23 @@ public:
|
||||
if (next)
|
||||
*B::prev_ptr(next)= *B::prev_ptr(a);
|
||||
**B::prev_ptr(a)= next;
|
||||
C::dec();
|
||||
}
|
||||
inline T* front() { return first; }
|
||||
inline const T *front() const { return first; }
|
||||
void swap(I_P_List<T,B> &rhs)
|
||||
void swap(I_P_List<T, B, C> &rhs)
|
||||
{
|
||||
swap_variables(T *, first, rhs.first);
|
||||
if (first)
|
||||
*B::prev_ptr(first)= &first;
|
||||
if (rhs.first)
|
||||
*B::prev_ptr(rhs.first)= &rhs.first;
|
||||
C::swap(rhs);
|
||||
}
|
||||
#ifndef _lint
|
||||
friend class I_P_List_iterator<T, B>;
|
||||
friend class I_P_List_iterator<T, B, C>;
|
||||
#endif
|
||||
typedef I_P_List_iterator<T, B> Iterator;
|
||||
typedef I_P_List_iterator<T, B, C> Iterator;
|
||||
};
|
||||
|
||||
|
||||
@ -129,15 +137,15 @@ public:
|
||||
Iterator for I_P_List.
|
||||
*/
|
||||
|
||||
template <typename T, typename B>
|
||||
template <typename T, typename B, typename C = I_P_List_null_counter>
|
||||
class I_P_List_iterator
|
||||
{
|
||||
const I_P_List<T, B> *list;
|
||||
const I_P_List<T, B, C> *list;
|
||||
T *current;
|
||||
public:
|
||||
I_P_List_iterator(const I_P_List<T, B> &a) : list(&a), current(a.first) {}
|
||||
I_P_List_iterator(const I_P_List<T, B> &a, T* current_arg) : list(&a), current(current_arg) {}
|
||||
inline void init(I_P_List<T, B> &a)
|
||||
I_P_List_iterator(const I_P_List<T, B, C> &a) : list(&a), current(a.first) {}
|
||||
I_P_List_iterator(const I_P_List<T, B, C> &a, T* current_arg) : list(&a), current(current_arg) {}
|
||||
inline void init(const I_P_List<T, B, C> &a)
|
||||
{
|
||||
list= &a;
|
||||
current= a.first;
|
||||
@ -160,4 +168,39 @@ public:
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
Element counting policy class for I_P_List to be used in
|
||||
cases when no element counting should be done.
|
||||
*/
|
||||
|
||||
class I_P_List_null_counter
|
||||
{
|
||||
protected:
|
||||
void reset() {}
|
||||
void inc() {}
|
||||
void dec() {}
|
||||
void swap(I_P_List_null_counter &rhs) {}
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
Element counting policy class for I_P_List which provides
|
||||
basic element counting.
|
||||
*/
|
||||
|
||||
class I_P_List_counter
|
||||
{
|
||||
uint m_counter;
|
||||
protected:
|
||||
I_P_List_counter() : m_counter (0) {}
|
||||
void reset() {m_counter= 0;}
|
||||
void inc() {m_counter++;}
|
||||
void dec() {m_counter--;}
|
||||
void swap(I_P_List_counter &rhs)
|
||||
{ swap_variables(uint, m_counter, rhs.m_counter); }
|
||||
public:
|
||||
uint elements() const { return m_counter; }
|
||||
};
|
||||
|
||||
#endif
|
||||
|
Reference in New Issue
Block a user