List:Commits« Previous MessageNext Message »
From:Davi Arnaut Date:February 12 2009 11:04pm
Subject:bzr push into mysql-6.0-runtime branch (davi:2800 to 2801) WL#4284
View as plain text  
 2801 Davi Arnaut	2009-02-12
      WL#4284: Transactional DDL locking
      
      Preparing for removing requests from the MDL subsystem.
      Remove reference counting by detaching requests from tickets.
      modified:
        sql/mdl.cc
        sql/mdl.h

 2800 Konstantin Osipov	2009-02-11
      WL#4284 "Transactional DDL locking"
      Review comments.
      Remove request from MDL_LOCK. A step on the path of removing
      requests from the MDL subsystem completely (they only need 
      to be used to add a ticket).
      Move enum mdl_state to MDL_LOCK_TICKET. Simplify the state:
      a ticket can be either pending, or acquired.
      modified:
        sql/mdl.cc
        sql/mdl.h

=== modified file 'sql/mdl.cc'
--- a/sql/mdl.cc	2009-02-10 22:38:38 +0000
+++ b/sql/mdl.cc	2009-02-12 22:00:31 +0000
@@ -765,7 +765,7 @@ bool mdl_acquire_shared_lock(MDL_CONTEXT
 
   /*
     Check whether the context already holds a shared lock on the object,
-    and if so, bump the ticket reference count and grant the request.
+    and if so, grant the request.
   */
   if ((ticket= mdl_context_find_ticket(context, lock_req)))
   {
@@ -1306,34 +1306,6 @@ bool mdl_wait_for_locks(MDL_CONTEXT *con
 
 
 /**
-  Decrement the reference count for a lock ticket. If the reference
-  count reaches zero, a provided release callback is called.
-
-  @param ticket   The lock ticket whose reference count should be decremented.
-  @param release  Callback function that performs the ticket release.
-
-  @return TRUE if the ticket was released, otherwise FALSE.
-*/
-
-typedef void (ticket_release_t)(MDL_CONTEXT *, MDL_LOCK_TICKET *);
-
-static inline bool ticket_unref(MDL_LOCK_TICKET *ticket,
-                                ticket_release_t *release)
-{
-  if (ticket->count == 1)
-  {
-    release(ticket->ctx, ticket);
-    return TRUE;
-  }
-  else
-  {
-    ticket->count--;
-    return FALSE;
-  }
-}
-
-
-/**
    Auxiliary function which allows to release particular lock
    ownership of which is represented by a lock ticket object.
 */
@@ -1347,8 +1319,6 @@ static void release_ticket(MDL_CONTEXT *
 
   safe_mutex_assert_owner(&LOCK_mdl);
 
-  DBUG_ASSERT(ticket->count == 1);
-
   context->tickets.remove(ticket);
 
   switch (ticket->type)
@@ -1386,21 +1356,6 @@ static void release_ticket(MDL_CONTEXT *
 
 
 /**
-   Wrapper function which takes LOCK_mdl before releasing a lock ticket.
-*/
-
-static void release_ticket_wrapper(MDL_CONTEXT *context, MDL_LOCK_TICKET *ticket)
-{
-  safe_mutex_assert_not_owner(&LOCK_open);
-
-  pthread_mutex_lock(&LOCK_mdl);
-  release_ticket(context, ticket);
-  pthread_cond_broadcast(&COND_mdl);
-  pthread_mutex_unlock(&LOCK_mdl);
-}
-
-
-/**
    Release all locks associated with the context, but leave them
    in the context as lock requests.
 
@@ -1414,36 +1369,36 @@ static void release_ticket_wrapper(MDL_C
 
 void mdl_ticket_release_all(MDL_CONTEXT *context)
 {
-  MDL_LOCK_REQUEST *lock_req;
-  MDL_CONTEXT::Request_iterator it(context->requests);
+  MDL_LOCK_TICKET *ticket;
+  MDL_CONTEXT::Ticket_iterator it(context->tickets);
   DBUG_ENTER("mdl_ticket_release_all");
 
   safe_mutex_assert_not_owner(&LOCK_open);
 
-  pthread_mutex_lock(&LOCK_mdl);
-  while ((lock_req= it++))
+  /* Detach lock tickets from the requests for back off. */
   {
-    DBUG_PRINT("info", ("found lock to release lock_req=%p", lock_req));
-    /*
-      Don't call release_lock() for a shared lock if has not been
-      granted.  We have pending and granted shared locks in the
-      same context when this function is called from the "back-off"
-      path of open_tables().
-    */
-    if (lock_req->ticket != NULL)
-    {
-      ticket_unref(lock_req->ticket, release_ticket);
+    MDL_LOCK_REQUEST *lock_req;
+    MDL_CONTEXT::Request_iterator it(context->requests);
+
+    while ((lock_req= it++))
       lock_req->ticket= NULL;
-    }
-    /*
-      We will return lock request to its initial state only in
-      mdl_request_remove_all() since we need to know type of lock
-      request in mdl_wait_for_locks().
-    */
+  }
+
+  if (context->tickets.is_empty())
+    DBUG_VOID_RETURN;
+
+  pthread_mutex_lock(&LOCK_mdl);
+  while ((ticket= it++))
+  {
+    DBUG_PRINT("info", ("found lock to release ticket=%p", ticket));
+    release_ticket(context, ticket);
   }
   /* Inefficient but will do for a while */
   pthread_cond_broadcast(&COND_mdl);
   pthread_mutex_unlock(&LOCK_mdl);
+
+  context->tickets.empty();
+
   DBUG_VOID_RETURN;
 }
 
@@ -1459,7 +1414,12 @@ void mdl_ticket_release_all(MDL_CONTEXT 
 void mdl_ticket_release(MDL_CONTEXT *context, MDL_LOCK_TICKET *ticket)
 {
   DBUG_ASSERT(context == ticket->ctx);
-  ticket_unref(ticket, release_ticket_wrapper);
+  safe_mutex_assert_not_owner(&LOCK_open);
+
+  pthread_mutex_lock(&LOCK_mdl);
+  release_ticket(context, ticket);
+  pthread_cond_broadcast(&COND_mdl);
+  pthread_mutex_unlock(&LOCK_mdl);
 }
 
 
@@ -1493,10 +1453,18 @@ void mdl_ticket_release_all_for_name(MDL
   {
     DBUG_ASSERT(lock_req->ticket && lock_req->ticket->state == MDL_ACQUIRED);
     if (lock_req->ticket->lock == lock)
-    {
-      mdl_ticket_release(context, lock_req->ticket);
       mdl_request_remove(context, lock_req);
-    }
+  }
+
+  /* Remove matching lock tickets from the context. */
+  MDL_LOCK_TICKET *lock_tkt;
+  MDL_CONTEXT::Ticket_iterator it_lock_tkt(context->tickets);
+
+  while ((lock_tkt= it_lock_tkt++))
+  {
+    DBUG_ASSERT(lock_tkt->state == MDL_ACQUIRED);
+    if (lock_tkt->lock == lock)
+      mdl_ticket_release(context, lock_tkt);
   }
 }
 

=== modified file 'sql/mdl.h'
--- a/sql/mdl.h	2009-02-10 22:38:38 +0000
+++ b/sql/mdl.h	2009-02-12 22:00:31 +0000
@@ -195,6 +195,14 @@ struct MDL_LOCK_TICKET
 
 struct MDL_CONTEXT
 {
+  typedef I_P_List<MDL_LOCK_REQUEST,
+                   I_P_List_adapter<MDL_LOCK_REQUEST,
+                                    &MDL_LOCK_REQUEST::next_in_context,
+                                    &MDL_LOCK_REQUEST::prev_in_context> >
+          Request_list;
+
+  typedef Request_list::Iterator Request_iterator;
+
   typedef I_P_List<MDL_LOCK_TICKET,
                    I_P_List_adapter<MDL_LOCK_TICKET,
                                     &MDL_LOCK_TICKET::next_in_context,
@@ -203,8 +211,8 @@ struct MDL_CONTEXT
 
   typedef Ticket_list::Iterator Ticket_iterator;
 
-  Ticket_list pending;
-  Ticket_list granted;
+  Request_list requests;
+  Ticket_list tickets;
   bool has_global_shared_lock;
   THD      *thd;
 };
@@ -224,6 +232,8 @@ void mdl_request_init(MDL_LOCK_REQUEST *
 MDL_LOCK_REQUEST *mdl_request_alloc(unsigned char type, const char *db,
                                     const char *name, MEM_ROOT *root);
 void mdl_request_add(MDL_CONTEXT *context, MDL_LOCK_REQUEST *lock_req);
+void mdl_request_remove(MDL_CONTEXT *context, MDL_LOCK_REQUEST *lock_req);
+void mdl_request_remove_all(MDL_CONTEXT *context);
 
 /**
    Set type of lock request. Can be only applied to pending locks.

Thread
bzr push into mysql-6.0-runtime branch (davi:2800 to 2801) WL#4284Davi Arnaut12 Feb