MDL_lock encapsulation: MDL_lock::remove_ticket()

Avoid accessing MDL_lock::m_waiting from MDL_context::acquire_lock(),
use MDL_lock::abort_wait() instead.

Avoid accessing MDL_lock::m_granted from MDL_context::release_lock(),
use MDL_lock::release() instead.

Avoid accessing MDL_lock::m_strategy and MDL_lock::m_rwlock from
MDL_map::remove(), code moved to MDL_lock::remove_ticket() instead.

This is part of broader cleanup, which aims to make large part of
MDL_lock members private. It is needed to simplify further work on
MDEV-19749 - MDL scalability regression after backup locks.
This commit is contained in:
Sergey Vojtovich
2025-05-01 15:29:53 +04:00
parent 5aa4ccf4c4
commit 2a3b999a56

View File

@ -175,7 +175,8 @@ public:
void destroy();
MDL_lock *find_or_insert(LF_PINS *pins, const MDL_key *key);
unsigned long get_lock_owner(LF_PINS *pins, const MDL_key *key);
void remove(LF_PINS *pins, MDL_lock *lock);
void remove(LF_PINS *pins, const MDL_key *key)
{ lf_hash_delete(&m_locks, pins, key->ptr(), key->length()); }
LF_PINS *get_pins() { return lf_hash_get_pins(&m_locks); }
private:
LF_HASH m_locks; /**< All acquired locks in the server. */
@ -791,6 +792,17 @@ end:
}
}
void release(LF_PINS *pins, MDL_ticket *ticket)
{
remove_ticket(pins, &MDL_lock::m_granted, ticket);
}
void abort_wait(LF_PINS *pins, MDL_ticket *ticket)
{ remove_ticket(pins, &MDL_lock::m_waiting, ticket); }
const MDL_lock_strategy *m_strategy;
private:
static const MDL_backup_lock m_backup_lock_strategy;
@ -996,27 +1008,6 @@ MDL_map::get_lock_owner(LF_PINS *pins, const MDL_key *mdl_key)
}
/**
Destroy MDL_lock object or delegate this responsibility to
whatever thread that holds the last outstanding reference to
it.
*/
void MDL_map::remove(LF_PINS *pins, MDL_lock *lock)
{
if (lock->key.mdl_namespace() == MDL_key::BACKUP)
{
/* Never destroy pre-allocated MDL_lock object in BACKUP namespace. */
mysql_prlock_unlock(&lock->m_rwlock);
return;
}
lock->m_strategy= 0;
mysql_prlock_unlock(&lock->m_rwlock);
lf_hash_delete(&m_locks, pins, lock->key.ptr(), lock->key.length());
}
/**
Initialize a metadata locking context.
@ -1886,7 +1877,13 @@ MDL_lock::can_grant_lock(enum_mdl_type type_arg,
}
/** Remove a ticket from waiting or pending queue and wakeup up waiters. */
/**
Removes ticket from waiting or pending queue and awakes waiters.
Once ticket is removed from the list, this thread doesn't hold
references to this lock and it can be destroyed concurrently. It
means once m_rwlock is released, "this" cannot be referenced anymore.
*/
void MDL_lock::remove_ticket(LF_PINS *pins, Ticket_list MDL_lock::*list,
MDL_ticket *ticket)
@ -1894,7 +1891,16 @@ void MDL_lock::remove_ticket(LF_PINS *pins, Ticket_list MDL_lock::*list,
mysql_prlock_wrlock(&m_rwlock);
(this->*list).remove_ticket(ticket);
if (is_empty())
mdl_locks.remove(pins, this);
{
/* Never destroy pre-allocated MDL_lock object in BACKUP namespace. */
if (key.mdl_namespace() != MDL_key::BACKUP)
{
m_strategy= 0;
mysql_prlock_unlock(&m_rwlock);
mdl_locks.remove(pins, &key);
return;
}
}
else
{
/*
@ -1912,8 +1918,8 @@ void MDL_lock::remove_ticket(LF_PINS *pins, Ticket_list MDL_lock::*list,
pending request).
*/
reschedule_waiters();
mysql_prlock_unlock(&m_rwlock);
}
mysql_prlock_unlock(&m_rwlock);
}
@ -2526,7 +2532,7 @@ MDL_context::acquire_lock(MDL_request *mdl_request, double lock_wait_timeout)
if (wait_status != MDL_wait::GRANTED)
{
lock->remove_ticket(m_pins, &MDL_lock::m_waiting, ticket);
lock->abort_wait(m_pins, ticket);
MDL_ticket::destroy(ticket);
switch (wait_status)
{
@ -2977,7 +2983,7 @@ void MDL_context::release_lock(enum_mdl_duration duration, MDL_ticket *ticket)
DBUG_ASSERT(this == ticket->get_ctx());
DBUG_PRINT("mdl", ("Released: %s", dbug_print_mdl(ticket)));
lock->remove_ticket(m_pins, &MDL_lock::m_granted, ticket);
lock->release(m_pins, ticket);
m_tickets[duration].remove(ticket);
MDL_ticket::destroy(ticket);