List:Maria Storage Engine« Previous MessageNext Message »
From:sanja Date:October 9 2008 12:12pm
Subject:bzr commit into MySQL/Maria:mysql-maria branch (sanja:2673) WL#3067 WL#3080
View as plain text  
#At bzr+ssh://bk-internal.mysql.com/bzrroot/server/mysql-maria/

 2673 sanja@stripped	2008-10-09
      Separated service thread framework to be used for update/delete purge (WL#3067) and group commit (WL#3080)
added:
  storage/maria/ma_servicethread.c
  storage/maria/ma_servicethread.h
modified:
  storage/maria/CMakeLists.txt
  storage/maria/Makefile.am
  storage/maria/ma_checkpoint.c

per-file messages:
  storage/maria/CMakeLists.txt
    Added files of service thread framework.
  storage/maria/Makefile.am
    Added files of service thread framework.
  storage/maria/ma_checkpoint.c
    Separated service thread framework.
  storage/maria/ma_servicethread.c
    Added files of service thread framework.
  storage/maria/ma_servicethread.h
    Added files of service thread framework.
=== modified file 'storage/maria/CMakeLists.txt'
--- a/storage/maria/CMakeLists.txt	2008-06-09 09:06:06 +0000
+++ b/storage/maria/CMakeLists.txt	2008-10-09 12:12:09 +0000
@@ -43,7 +43,7 @@ SET(MARIA_SOURCES ma_init.c ma_open.c ma
             ma_sp_key.c ma_control_file.c ma_loghandler.c 
             ma_pagecache.c ma_pagecaches.c 
             ma_checkpoint.c ma_recovery.c ma_commit.c ma_pagecrc.c
-            ha_maria.h maria_def.h ma_recovery_util.c
+            ha_maria.h maria_def.h ma_recovery_util.c ma_servicethread.c
 )
 
 IF(NOT SOURCE_SUBLIBS)

=== modified file 'storage/maria/Makefile.am'
--- a/storage/maria/Makefile.am	2008-06-26 05:18:28 +0000
+++ b/storage/maria/Makefile.am	2008-10-09 12:12:09 +0000
@@ -73,7 +73,7 @@ noinst_HEADERS =	maria_def.h ma_rt_index
 			ma_loghandler.h ma_loghandler_lsn.h ma_pagecache.h \
 			ma_checkpoint.h ma_recovery.h ma_commit.h ma_state.h \
 			trnman_public.h ma_check_standalone.h \
-			ma_key_recover.h ma_recovery_util.h
+			ma_key_recover.h ma_recovery_util.h ma_servicethread.h
 ma_test1_DEPENDENCIES=	$(LIBRARIES)
 ma_test1_LDADD=		@CLIENT_EXTRA_LDFLAGS@ libmaria.a \
                         $(top_builddir)/storage/myisam/libmyisam.a \
@@ -135,7 +135,7 @@ libmaria_a_SOURCES =	ma_init.c ma_open.c
 			ma_pagecache.c ma_pagecaches.c \
 			ma_checkpoint.c ma_recovery.c ma_commit.c \
 			ma_pagecrc.c ma_recovery_util.c \
-			ha_maria.cc
+			ha_maria.cc ma_servicethread.c
 CLEANFILES =		test?.MA? FT?.MA? isam.log ma_test_all ma_rt_test.MA? sp_test.MA? maria_log_control maria_log.0000*
 
 SUFFIXES = .sh

=== modified file 'storage/maria/ma_checkpoint.c'
--- a/storage/maria/ma_checkpoint.c	2008-08-28 18:52:23 +0000
+++ b/storage/maria/ma_checkpoint.c	2008-10-09 12:12:09 +0000
@@ -35,6 +35,7 @@
 #include "ma_blockrec.h"
 #include "ma_checkpoint.h"
 #include "ma_loghandler_lsn.h"
+#include "ma_servicethread.h"
 
 
 /** @brief type of checkpoint currently running */
@@ -43,10 +44,9 @@ static CHECKPOINT_LEVEL checkpoint_in_pr
 static pthread_mutex_t LOCK_checkpoint;
 /** @brief for killing the background checkpoint thread */
 static pthread_cond_t  COND_checkpoint;
-/** @brief if checkpoint module was inited or not */
-static my_bool checkpoint_inited= FALSE;
-/** @brief 'kill' flag for the background checkpoint thread */
-static int checkpoint_thread_die;
+/** @brief control structure for checkpoint background thread */
+static MA_SERVICE_THREAD_CONTROL checkpoint_control=
+  {THREAD_DEAD, FALSE, &LOCK_checkpoint, &COND_checkpoint};
 /* is ulong like pagecache->blocks_changed */
 static ulong pages_to_flush_before_next_checkpoint;
 static PAGECACHE_FILE *dfiles, /**< data files to flush in background */
@@ -99,7 +99,7 @@ int ma_checkpoint_execute(CHECKPOINT_LEV
   int result= 0;
   DBUG_ENTER("ma_checkpoint_execute");
 
-  if (!checkpoint_inited)
+  if (!checkpoint_control.inited)
   {
     /*
       If ha_maria failed to start, maria_panic_hton is called, we come here.
@@ -326,17 +326,14 @@ int ma_checkpoint_init(ulong interval)
   pthread_t th;
   int res= 0;
   DBUG_ENTER("ma_checkpoint_init");
-  checkpoint_inited= TRUE;
-  checkpoint_thread_die= 2; /* not yet born == dead */
-  if (pthread_mutex_init(&LOCK_checkpoint, MY_MUTEX_INIT_SLOW) ||
-      pthread_cond_init(&COND_checkpoint, 0))
+  if (ma_service_thread_control_init(&checkpoint_control))
     res= 1;
   else if (interval > 0)
   {
     compile_time_assert(sizeof(void *) >= sizeof(ulong));
     if (!(res= pthread_create(&th, NULL, ma_checkpoint_background,
                               (void *)interval)))
-      checkpoint_thread_die= 0; /* thread lives, will have to be killed */
+      checkpoint_control.status= THREAD_RUNNING; /* thread rlives, will have to be killed */
   }
   DBUG_RETURN(res);
 }
@@ -423,30 +420,12 @@ void ma_checkpoint_end(void)
   DBUG_EXECUTE_IF("maria_crash",
                   { DBUG_PRINT("maria_crash", ("now")); DBUG_ABORT(); });
 
-  if (checkpoint_inited)
+  if (checkpoint_control.inited)
   {
-    pthread_mutex_lock(&LOCK_checkpoint);
-    if (checkpoint_thread_die != 2) /* thread was started ok */
-    {
-      DBUG_PRINT("info",("killing Maria background checkpoint thread"));
-      checkpoint_thread_die= 1; /* kill it */
-      do /* and wait for it to be dead */
-      {
-        /* wake it up if it was in a sleep */
-        pthread_cond_broadcast(&COND_checkpoint);
-        DBUG_PRINT("info",("waiting for Maria background checkpoint thread"
-                           " to die"));
-        pthread_cond_wait(&COND_checkpoint, &LOCK_checkpoint);
-      }
-      while (checkpoint_thread_die != 2);
-    }
-    pthread_mutex_unlock(&LOCK_checkpoint);
+    ma_service_thread_control_end(&checkpoint_control);
     my_free((uchar *)dfiles, MYF(MY_ALLOW_ZERO_PTR));
     my_free((uchar *)kfiles, MYF(MY_ALLOW_ZERO_PTR));
     dfiles= kfiles= NULL;
-    pthread_mutex_destroy(&LOCK_checkpoint);
-    pthread_cond_destroy(&COND_checkpoint);
-    checkpoint_inited= FALSE;
   }
   DBUG_VOID_RETURN;
 }
@@ -586,7 +565,6 @@ pthread_handler_t ma_checkpoint_backgrou
 #if 0 /* good for testing, to do a lot of checkpoints, finds a lot of bugs */
     sleeps=0;
 #endif
-    struct timespec abstime;
     switch (sleeps % interval)
     {
     case 0:
@@ -691,25 +669,11 @@ pthread_handler_t ma_checkpoint_backgrou
         sleep_time= interval - (sleeps % interval);
       }
     }
-    pthread_mutex_lock(&LOCK_checkpoint);
-    if (checkpoint_thread_die == 1)
+    if (my_service_thread_sleep(&checkpoint_control,
+                                sleep_time * 1000000000ULL))
       break;
-#if 0 /* good for testing, to do a lot of checkpoints, finds a lot of bugs */
-    pthread_mutex_unlock(&LOCK_checkpoint);
-    my_sleep(100000); /* a tenth of a second */
-    pthread_mutex_lock(&LOCK_checkpoint);
-#else
-    /* To have a killable sleep, we use timedwait like our SQL GET_LOCK() */
-    DBUG_PRINT("info", ("sleeping %u seconds", sleep_time));
-    set_timespec(abstime, sleep_time);
-    pthread_cond_timedwait(&COND_checkpoint, &LOCK_checkpoint, &abstime);
-#endif
-    if (checkpoint_thread_die == 1)
-      break;
-    pthread_mutex_unlock(&LOCK_checkpoint);
     sleeps+= sleep_time;
   }
-  pthread_mutex_unlock(&LOCK_checkpoint);
   DBUG_PRINT("info",("Maria background checkpoint thread ends"));
   {
     CHECKPOINT_LEVEL level= CHECKPOINT_FULL;
@@ -720,12 +684,7 @@ pthread_handler_t ma_checkpoint_backgrou
     DBUG_EXECUTE_IF("maria_checkpoint_indirect", level= CHECKPOINT_INDIRECT;);
     ma_checkpoint_execute(level, FALSE);
   }
-  pthread_mutex_lock(&LOCK_checkpoint);
-  checkpoint_thread_die= 2; /* indicate that we are dead */
-  /* wake up ma_checkpoint_end() which may be waiting for our death */
-  pthread_cond_broadcast(&COND_checkpoint);
-  /* broadcast was inside unlock because ma_checkpoint_end() destroys mutex */
-  pthread_mutex_unlock(&LOCK_checkpoint);
+  my_service_thread_signal_end(&checkpoint_control);
   my_thread_end();
   return 0;
 }

=== added file 'storage/maria/ma_servicethread.c'
--- a/storage/maria/ma_servicethread.c	1970-01-01 00:00:00 +0000
+++ b/storage/maria/ma_servicethread.c	2008-10-09 12:12:09 +0000
@@ -0,0 +1,132 @@
+#include "maria_def.h"
+#include "ma_servicethread.h"
+
+/**
+   @brief Initializes the service thread
+
+   @param control        control block
+
+   @return Operation status
+    @retval 0 OK
+    @retval 1 error
+*/
+
+int ma_service_thread_control_init(MA_SERVICE_THREAD_CONTROL *control)
+{
+  int res= 0;
+  DBUG_ENTER("ma_service_thread_control_init");
+  DBUG_PRINT("init", ("control 0x%lx", (ulong) control));
+  control->inited= TRUE;
+  control->status= THREAD_DEAD; /* not yet born == dead */
+  if (pthread_mutex_init(control->LOCK_control, MY_MUTEX_INIT_SLOW) ||
+      pthread_cond_init(control->COND_control, 0))
+    res= 1;
+  DBUG_RETURN(res);
+}
+
+
+/**
+   @brief Kill the service thread
+
+   @param control        control block
+
+   @note The service thread should react on condition and status equal
+   THREAD_DIEING, by setting status THREAD_DEAD, and issuing message to
+   control thread via condition and exiting. The base way to do so is using
+   my_service_thread_sleep() and my_service_thread_signal_end()
+*/
+
+void ma_service_thread_control_end(MA_SERVICE_THREAD_CONTROL *control)
+{
+  DBUG_ENTER("ma_service_thread_control_end");
+  DBUG_PRINT("init", ("control 0x%lx", (ulong) control));
+  DBUG_ASSERT(control->inited);
+  pthread_mutex_lock(control->LOCK_control);
+  if (control->status != THREAD_DEAD) /* thread was started OK */
+  {
+    DBUG_PRINT("info",("killing Maria background thread"));
+    control->status= THREAD_DIEING; /* kill it */
+    do /* and wait for it to be dead */
+    {
+      /* wake it up if it was in a sleep */
+      pthread_cond_broadcast(control->COND_control);
+      DBUG_PRINT("info",("waiting for Maria background thread"
+                         " to die"));
+      pthread_cond_wait(control->COND_control, control->LOCK_control);
+    }
+    while (control->status != THREAD_DEAD);
+  }
+  pthread_mutex_unlock(control->LOCK_control);
+  pthread_mutex_destroy(control->LOCK_control);
+  pthread_cond_destroy(control->COND_control);
+  control->inited= FALSE;
+  DBUG_VOID_RETURN;
+}
+
+
+/**
+   @brief Sleep for given number of nanoseconds with reaction on thread kill
+
+   @param control        control block
+   @param sleep_time     time of sleeping
+
+   @return Operation status
+    @retval 0 Time out
+    @retval 1 Thread should be killed
+*/
+
+my_bool my_service_thread_sleep(MA_SERVICE_THREAD_CONTROL *control,
+                                ulonglong sleep_time)
+{
+  struct timespec abstime;
+  my_bool res= 0;
+  DBUG_ENTER("my_service_thread_sleep");
+  DBUG_PRINT("init", ("control 0x%lx", (ulong) control));
+  pthread_mutex_lock(control->LOCK_control);
+  if (control->status == THREAD_DIEING)
+  {
+    pthread_mutex_unlock(control->LOCK_control);
+    DBUG_RETURN(1);
+  }
+#if 0 /* good for testing, to do a lot of checkpoints, finds a lot of bugs */
+  pthread_mutex_unlock(&LOCK_checkpoint);
+  my_sleep(100000); /* a tenth of a second */
+  pthread_mutex_lock(&LOCK_checkpoint);
+#else
+    /* To have a killable sleep, we use timedwait like our SQL GET_LOCK() */
+  DBUG_PRINT("info", ("sleeping %llu nano seconds", sleep_time));
+  set_timespec_nsec(abstime, sleep_time);
+  pthread_cond_timedwait(control->COND_control,
+                         control->LOCK_control, &abstime);
+#endif
+  if (control->status == THREAD_DIEING)
+    res= 1;
+  pthread_mutex_unlock(control->LOCK_control);
+  DBUG_RETURN(res);
+}
+
+
+/**
+  @brief inform about thread exiting
+
+  @param control        control block
+*/
+
+void my_service_thread_signal_end(MA_SERVICE_THREAD_CONTROL *control)
+{
+  DBUG_ENTER("my_service_thread_signal_end");
+  DBUG_PRINT("init", ("control 0x%lx", (ulong) control));
+  pthread_mutex_lock(control->LOCK_control);
+  control->status = THREAD_DEAD; /* indicate that we are dead */
+  /*
+    wake up ma_service_thread_control_end which may be waiting for
+    our death
+  */
+  pthread_cond_broadcast(control->COND_control);
+  /*
+    broadcast was inside unlock because ma_service_thread_control_end
+    destroys mutex
+  */
+  pthread_mutex_unlock(control->LOCK_control);
+  DBUG_VOID_RETURN;
+}

=== added file 'storage/maria/ma_servicethread.h'
--- a/storage/maria/ma_servicethread.h	1970-01-01 00:00:00 +0000
+++ b/storage/maria/ma_servicethread.h	2008-10-09 12:12:09 +0000
@@ -0,0 +1,22 @@
+#include <my_pthread.h>
+
+enum ma_service_thread_state {THREAD_RUNNING, THREAD_DIEING, THREAD_DEAD};
+
+typedef struct st_ma_service_thread_control
+{
+  /** @brief 'kill' flag for the background thread */
+  enum ma_service_thread_state status;
+  /** @brief if thread module was inited or not */
+  my_bool inited;
+  /** @brief for killing the background thread */
+  pthread_mutex_t *LOCK_control;
+  /** @brief for killing the background thread */
+  pthread_cond_t *COND_control;
+} MA_SERVICE_THREAD_CONTROL;
+
+
+int ma_service_thread_control_init(MA_SERVICE_THREAD_CONTROL *control);
+void ma_service_thread_control_end(MA_SERVICE_THREAD_CONTROL *control);
+my_bool my_service_thread_sleep(MA_SERVICE_THREAD_CONTROL *control,
+                                ulonglong sleep_time);
+void my_service_thread_signal_end(MA_SERVICE_THREAD_CONTROL *control);

Thread
bzr commit into MySQL/Maria:mysql-maria branch (sanja:2673) WL#3067 WL#3080sanja9 Oct
  • Re: bzr commit into MySQL/Maria:mysql-maria branch (sanja:2673)WL#3067 WL#3080Guilhem Bichot12 Jan