List:Commits« Previous MessageNext Message »
From:Chuck Bell Date:July 2 2008 7:38pm
Subject:bzr commit into mysql-6.0-backup branch (cbell:2648) Bug#35230
View as plain text  
#At file:///D:/source/bzr/mysql-6.0-bug-35230/

 2648 Chuck Bell	2008-07-02
      BUG#35230 Backup: no backupdir 
      
      This patch adds the dynamic variable --backupdir which specifies the path where the image files
      are placed (backup) or accessed (restore) if a path is not specified in the command.
      
      The default is the same as --datadir.
modified:
  include/config-netware.h
  include/config-win.h
  mysql-test/mysql-test-run.pl
  mysql-test/r/backup_progress.result
  mysql-test/t/backup_progress.test
  scripts/mysqld_safe.sh
  sql/backup/kernel.cc
  sql/mysqld.cc
  sql/set_var.cc
  sql/set_var.h
  sql/share/errmsg.txt
  sql/unireg.h

per-file messages:
  include/config-netware.h
    Added #define for backupdir.
  include/config-win.h
    Added #define for backupdir.
  mysql-test/mysql-test-run.pl
    Added backupdir to MTR to properly set the default path for test runs.
  mysql-test/r/backup_progress.result
    New result file.
  mysql-test/t/backup_progress.test
    Added a mask for backup location because this path will vary from machine to machine.
  scripts/mysqld_safe.sh
    Added setting of backupdir for launching on Linux systems.
  sql/backup/kernel.cc
    Added code to process the backupdir IFF there is no path specified in the command.
  sql/mysqld.cc
    Added code to support backupdir.
  sql/set_var.cc
    Added all of the methods needed to check, update, and set a default for the backupdir variable.
  sql/set_var.h
    Added extern for backupdir variable named sys_var_backupdir.
  sql/share/errmsg.txt
    Added new error message for invalid backupdir paths.
  sql/unireg.h
    Added #define for backupdir.
=== modified file 'include/config-netware.h'
--- a/include/config-netware.h	2007-07-23 21:54:55 +0000
+++ b/include/config-netware.h	2008-07-02 19:37:44 +0000
@@ -132,6 +132,7 @@ extern "C" {
 #define SHAREDIR              "share/"
 #define DEFAULT_CHARSET_HOME  "sys:/mysql/"
 #define DATADIR               "data/"
+#define BACKUPDIR             "data/"
 
 /* 64-bit file system calls */
 #define SIZEOF_OFF_T          8

=== modified file 'include/config-win.h'
--- a/include/config-win.h	2008-07-02 11:27:17 +0000
+++ b/include/config-win.h	2008-07-02 19:37:44 +0000
@@ -341,6 +341,7 @@ inline double ulonglong2double(ulonglong
 #else
 #define DEFAULT_MYSQL_HOME	"c:\\mysql"
 #define DATADIR         	"c:\\mysql\\data"
+#define BACKUPDIR        	"c:\\mysql\\data"
 #define PACKAGE			"mysql"
 #define DEFAULT_BASEDIR		"C:\\"
 #define SHAREDIR		"share"

=== modified file 'mysql-test/mysql-test-run.pl'
--- a/mysql-test/mysql-test-run.pl	2008-07-02 07:53:34 +0000
+++ b/mysql-test/mysql-test-run.pl	2008-07-02 19:37:44 +0000
@@ -3663,6 +3663,17 @@ sub mysqld_arguments ($$$$) {
   mtr_add_arg($args, "%s--datadir=%s", $prefix,
 	      $mysqld->{'path_myddir'});
 
+  #
+  # Add the --backupdir parameter for running backup tests from MTR.
+  # Note: In the future, this setting should be moved to an option
+  # file located in the backup suite directory. The file should contain
+  # the following and be named 'suite.opt':
+  #
+  # --backupdir=$MYSQLTEST_VARDIR/tmp
+  #
+  mtr_add_arg($args, "%s--backupdir=%s", $prefix,
+	      $mysqld->{'path_myddir'});
+
 
   if ( $mysql_version_id >= 50106 )
   {

=== modified file 'mysql-test/r/backup_progress.result'
--- a/mysql-test/r/backup_progress.result	2008-07-01 20:32:27 +0000
+++ b/mysql-test/r/backup_progress.result	2008-07-02 19:37:44 +0000
@@ -78,7 +78,7 @@ start_time	#
 stop_time	#
 host_or_server_name	localhost
 username	root
-backup_file	backup_progress_orig.bak
+backup_file	#
 user_comment	
 command	BACKUP DATABASE backup_progress to 'backup_progress_orig.bak'
 engines	MyISAM, Default, Snapshot
@@ -135,7 +135,7 @@ start_time	#
 stop_time	#
 host_or_server_name	localhost
 username	root
-backup_file	backup_progress_orig.bak
+backup_file	#
 user_comment	
 command	RESTORE FROM 'backup_progress_orig.bak'
 engines	MyISAM, Default, Snapshot

=== modified file 'mysql-test/t/backup_progress.test'
--- a/mysql-test/t/backup_progress.test	2008-06-25 13:39:04 +0000
+++ b/mysql-test/t/backup_progress.test	2008-07-02 19:37:44 +0000
@@ -107,7 +107,7 @@ connection con2;
 reap;
 
 #Show results
---replace_column 1 # 2 # 3 # 4 # 10 # 11 # 12 #
+--replace_column 1 # 2 # 3 # 4 # 10 # 11 # 12 # 15 #
 --query_vertical SELECT ob.* FROM mysql.online_backup AS ob JOIN backup_progress.t1_res AS t1 ON ob.backup_id = t1.id;
 --replace_column 1 # 3 # 4 #
 SELECT obp.* FROM mysql.online_backup_progress AS obp JOIN backup_progress.t1_res AS t1 ON obp.backup_id = t1.id;
@@ -156,7 +156,7 @@ reap;
 DELETE FROM backup_progress.t1_res;
 SELECT MAX(backup_id) INTO @bup_id FROM mysql.online_backup WHERE command LIKE "RESTORE FROM%";
 INSERT INTO backup_progress.t1_res (id) VALUES (@bup_id);
---replace_column 1 # 2 # 3 # 4 # 10 # 11 # 12 #
+--replace_column 1 # 2 # 3 # 4 # 10 # 11 # 12 # 15 #
 --query_vertical SELECT ob.* FROM mysql.online_backup AS ob JOIN backup_progress.t1_res AS t1 ON ob.backup_id = t1.id;
 --replace_column 1 # 3 # 4 #
 SELECT obp.* FROM mysql.online_backup_progress AS obp JOIN backup_progress.t1_res AS t1 ON obp.backup_id = t1.id;

=== modified file 'scripts/mysqld_safe.sh'
--- a/scripts/mysqld_safe.sh	2008-03-11 16:15:47 +0000
+++ b/scripts/mysqld_safe.sh	2008-07-02 19:37:44 +0000
@@ -156,6 +156,7 @@ parse_arguments() {
       # these get passed explicitly to mysqld
       --basedir=*) MY_BASEDIR_VERSION="$val" ;;
       --datadir=*) DATADIR="$val" ;;
+      --backupdir=*) DATADIR="$val" ;;
       --pid-file=*) pid_file="$val" ;;
       --user=*) user="$val"; SET_USER=1 ;;
 
@@ -534,7 +535,7 @@ fi
 cmd="$NOHUP_NICENESS"
 
 for i in  "$ledir/$MYSQLD" "$defaults" "--basedir=$MY_BASEDIR_VERSION" \
-  "--datadir=$DATADIR" "$USER_OPTION"
+  "--datadir=$DATADIR" "--backupdir=$DATADIR" "$USER_OPTION"
 do
   cmd="$cmd "`shell_quote_string "$i"`
 done

=== modified file 'sql/backup/kernel.cc'
--- a/sql/backup/kernel.cc	2008-07-01 13:34:36 +0000
+++ b/sql/backup/kernel.cc	2008-07-02 19:37:44 +0000
@@ -122,6 +122,8 @@ int
 execute_backup_command(THD *thd, LEX *lex)
 {
   int res= 0;
+  LEX_STRING path;
+  int path_len= 0;
   
   DBUG_ENTER("execute_backup_command");
   DBUG_ASSERT(thd && lex);
@@ -134,13 +136,31 @@ execute_backup_command(THD *thd, LEX *le
   if (!context.is_valid())
     DBUG_RETURN(send_error(context, ER_BACKUP_CONTEXT_CREATE));
 
+  /*
+    Prepare the path using the backupdir iff no path included
+  */
+  if (!has_path(lex->backup_dir.str))
+  {
+    path.length= sys_var_backupdir.value_length + lex->backup_dir.length + 1;
+    path.str= (char *)my_malloc(path.length + 1, MYF(0));
+    strcpy(path.str, fn_format(path.str, lex->backup_dir.str, 
+                               sys_var_backupdir.value, "",
+                               MY_UNPACK_FILENAME));
+  }
+  else
+  {
+    path.length= lex->backup_dir.length + 1;
+    path.str= (char *)my_malloc(path.length + 1, MYF(0));
+    strcpy(path.str, lex->backup_dir.str);
+  }
+
   switch (lex->sql_command) {
 
   case SQLCOM_BACKUP:
   {
     // prepare for backup operation
     
-    Backup_info *info= context.prepare_for_backup(lex->backup_dir, thd->query,
+    Backup_info *info= context.prepare_for_backup(path, thd->query,
                                                   lex->backup_compression);
                                                               // reports errors
 
@@ -185,7 +205,7 @@ execute_backup_command(THD *thd, LEX *le
 
   case SQLCOM_RESTORE:
   {
-    Restore_info *info= context.prepare_for_restore(lex->backup_dir, thd->query);
+    Restore_info *info= context.prepare_for_restore(path, thd->query);
     
     if (!info || !info->is_valid())
       DBUG_RETURN(send_error(context, ER_BACKUP_RESTORE_PREPARE));
@@ -209,6 +229,7 @@ execute_backup_command(THD *thd, LEX *le
 
   } // switch(lex->sql_command)
 
+  my_free(path.str, MYF(0));  // free memory for path
   if (context.close())
     DBUG_RETURN(send_error(context, ER_BACKUP_CONTEXT_REMOVE));
 
@@ -396,7 +417,12 @@ int Backup_restore_ctx::prepare(LEX_STRI
 
   // check if location is valid (we assume it is a file path)
 
-  bool bad_filename= (location.length == 0);
+  /*
+    For this error to work correctly, we need to check original
+    file specified by the user rather than the path formed
+    using the backupdir.
+  */
+  bool bad_filename= (m_thd->lex->backup_dir.length == 0);
   
   /*
     On some systems certain file names are invalid. We use 
@@ -404,13 +430,13 @@ int Backup_restore_ctx::prepare(LEX_STRI
    */ 
 #if defined(__WIN__) || defined(__EMX__)  
 
-  bad_filename = bad_filename || check_if_legal_filename(location.str);
-  
+  bad_filename = bad_filename || check_if_legal_filename(m_thd->lex->backup_dir.str);
+
 #endif
 
   if (bad_filename)
   {
-    fatal_error(ER_BAD_PATH, location.str);
+    fatal_error(ER_BAD_PATH, m_thd->lex->backup_dir.str);
     return m_error;
   }
 
@@ -499,7 +525,12 @@ Backup_restore_ctx::prepare_for_backup(L
   
   if (!s->open())
   {
-    fatal_error(ER_BACKUP_WRITE_LOC, path.ptr());
+    /*
+      For this error, use the actual value returned instead of the
+      path complimented with backupdir.
+    */
+    THD *thd= ::current_thd;
+    fatal_error(ER_BACKUP_WRITE_LOC, thd->lex->backup_dir.str);
     return NULL;
   }
 
@@ -576,7 +607,12 @@ Backup_restore_ctx::prepare_for_restore(
   
   if (!s->open())
   {
-    fatal_error(ER_BACKUP_READ_LOC, path.ptr());
+    /*
+      For this error, use the actual value returned instead of the
+      path complimented with backupdir.
+    */
+    THD *thd= ::current_thd;
+    fatal_error(ER_BACKUP_READ_LOC, thd->lex->backup_dir.str);
     return NULL;
   }
 

=== modified file 'sql/mysqld.cc'
--- a/sql/mysqld.cc	2008-07-01 20:32:27 +0000
+++ b/sql/mysqld.cc	2008-07-02 19:37:44 +0000
@@ -1362,6 +1362,7 @@ void clean_up(bool print_message)
   my_free(sys_init_slave.value, MYF(MY_ALLOW_ZERO_PTR));
   my_free(sys_var_general_log_path.value, MYF(MY_ALLOW_ZERO_PTR));
   my_free(sys_var_slow_log_path.value, MYF(MY_ALLOW_ZERO_PTR));
+  my_free(sys_var_backupdir.value, MYF(MY_ALLOW_ZERO_PTR));
   free_tmpdir(&mysql_tmpdir_list);
 #ifdef HAVE_REPLICATION
   my_free(slave_load_tmpdir,MYF(MY_ALLOW_ZERO_PTR));
@@ -5745,6 +5746,8 @@ struct my_option my_long_options[] =
    "Creating and dropping stored procedures alters ACLs. Disable with --skip-automatic-sp-privileges.",
    (uchar**) &sp_automatic_privileges, (uchar**) &sp_automatic_privileges,
    0, GET_BOOL, NO_ARG, 1, 0, 0, 0, 0, 0},
+  {"backupdir", 'B', "Path used to store backup data.", (uchar**) &sys_var_backupdir.value,
+   (uchar**) &sys_var_backupdir.value, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
   {"basedir", 'b',
    "Path to installation directory. All paths are usually resolved relative to this.",
    (uchar**) &mysql_home_ptr, (uchar**) &mysql_home_ptr, 0, GET_STR, REQUIRED_ARG,
@@ -7853,6 +7856,22 @@ mysqld_get_one_option(int optid,
   case 'l':
     opt_log=1;
     break;
+  case 'B':
+  {
+    /*
+      Check if directory exists and we have permission to create file and
+      write to file.
+    */
+    if (my_access(argument, (F_OK|W_OK)))
+    {
+      fprintf(stderr, "The path specified for the variable backupdir cannot"
+        " be accessed or is invalid. ref:'%s'\n", argument);
+      exit(1);
+    }
+    strcpy(sys_var_backupdir.value, argument);
+    sys_var_backupdir.value_length= strlen(sys_var_backupdir.value);
+    break;
+  }
   case 'h':
     strmake(mysql_real_data_home,argument, sizeof(mysql_real_data_home)-1);
     /* Correct pointer set by my_getopt (for embedded library) */

=== modified file 'sql/set_var.cc'
--- a/sql/set_var.cc	2008-05-27 19:47:15 +0000
+++ b/sql/set_var.cc	2008-07-02 19:37:44 +0000
@@ -149,6 +149,9 @@ static bool sys_update_general_log_path(
 static void sys_default_general_log_path(THD *thd, enum_var_type type);
 static bool sys_update_slow_log_path(THD *thd, set_var * var);
 static void sys_default_slow_log_path(THD *thd, enum_var_type type);
+static int sys_check_backupdir(THD *thd, set_var *var);
+static bool sys_update_backupdir(THD *thd, set_var * var);
+static void sys_default_backupdir(THD *thd, enum_var_type type);
 
 /*
   Variable definition list
@@ -778,6 +781,15 @@ sys_var_str sys_var_slow_log_path(&vars,
 				  opt_slow_logname);
 static sys_var_log_output sys_var_log_output_state(&vars, "log_output", &log_output_options,
 					    &log_output_typelib, 0);
+
+/*
+  Create the backupdir dynamic variable.
+*/
+sys_var_str sys_var_backupdir(&vars, "backupdir",
+                              sys_check_backupdir,
+                              sys_update_backupdir,
+                              sys_default_backupdir,
+                               0);
 
 
 /*
@@ -2614,6 +2626,142 @@ uchar *sys_var_log_output::value_ptr(THD
   return (uchar*) thd->strmake(tmp.ptr(), length);
 }
 
+/*
+  Functions for backupdir variable.
+*/
+
+/**
+  Set the default for the backupdir
+
+  @param[IN] buff Buffer to use for making string.
+
+  @returns pointer to string (buff)
+*/
+char *make_default_backupdir(char *buff)
+{
+  strmake(buff, mysql_data_home, FN_REFLEN-5);
+  return buff;
+}
+
+/**
+  Check the backupdir value for validity.
+
+  This method ensures the users is specifying a valid path
+  for the backupdir. Validity in this case means the path
+  is accessible to the user.
+
+  @param[IN] thd   Current thread context.
+  @param[IN] var   The new value set in set_var structure.
+
+  @returns 0 valid, 1 invalid.
+*/
+static int sys_check_backupdir(THD *thd, set_var *var)
+{
+  char path[FN_REFLEN], buff[FN_REFLEN];
+  MY_STAT f_stat;
+  String str(buff, sizeof(buff), system_charset_info), *res;
+  const char *log_file_str;
+  size_t path_length;
+
+  if (!(res= var->value->val_str(&str)))
+    goto err;
+
+  log_file_str= res->c_ptr();
+  bzero(&f_stat, sizeof(MY_STAT));
+
+  /* Get dirname of the file path. */
+  (void) dirname_part(path, log_file_str, &path_length);
+
+  /* Dirname is empty if file path is relative. */
+  if (!path_length)
+    return 0;
+
+  /*
+    Check if directory exists and we have permission to create file and
+    write to file.
+  */
+  if (my_access(path, (F_OK|W_OK)))
+    goto err;
+
+  return 0;
+
+err:
+  my_error(ER_BACKUP_BACKUPDIR, MYF(0), var->value->str_value.c_ptr());
+  return 1;
+}
+
+/**
+  Update the backupdir variable 
+  
+  This method is used to change the backupdir variable.
+
+  @param[IN] thd   Current thread context.
+  @param[IN] var   The new value set in set_var structure.
+
+  @returns 0 valid, 1 invalid.
+*/
+static bool sys_update_backupdir(THD *thd, set_var * var)
+{
+  char buff[FN_REFLEN];
+  char *res= 0, *old_value=(char *)(var ? var->value->str_value.ptr() : 0);
+  bool result= 0;
+  uint str_length= (var ? var->value->str_value.length() : 0);
+
+  if (!old_value)
+  {
+    old_value= make_default_backupdir(buff);
+    str_length= strlen(old_value);
+  }
+  if (!(res= my_strndup(old_value, str_length, MYF(MY_FAE+MY_WME))))
+  {
+    result= 1;
+    goto err;
+  }
+
+  pthread_mutex_lock(&LOCK_global_system_variables);
+  logger.lock_exclusive();
+  old_value= sys_var_backupdir.value;
+  sys_var_backupdir.value= res;
+  sys_var_backupdir.value_length= str_length;
+  logger.unlock();
+  pthread_mutex_unlock(&LOCK_global_system_variables);
+
+  if (my_access(sys_var_backupdir.value, (F_OK|W_OK)))
+  {
+    /*
+      There is a problem accessing backupdir specified. Revert to old
+      one and throw error.
+    */
+    if (old_value)
+    {
+      sys_var_backupdir.value= old_value;
+      sys_var_backupdir.value_length= strlen(old_value);
+    }
+    result= 1;
+    goto err;
+  }
+
+  return result;
+
+err:
+  my_error(ER_BACKUP_BACKUPDIR, MYF(0), var->value->str_value.c_ptr());
+  return result;
+}
+
+/**
+  Set the default value for the backupdir variable 
+  
+  This method is used to reset the backupdir variable to the
+  default by calling the update method without a path.
+
+  @param[IN] thd   Current thread context.
+  @param[IN] type  Ignored (needed for api).
+*/
+static void sys_default_backupdir(THD *thd, enum_var_type type)
+{
+  sys_update_backupdir(thd, 0);
+}
+
 
 /*****************************************************************************
   Functions to handle SET NAMES and SET CHARACTER SET

=== modified file 'sql/set_var.h'
--- a/sql/set_var.h	2008-05-27 19:47:15 +0000
+++ b/sql/set_var.h	2008-07-02 19:37:44 +0000
@@ -1345,7 +1345,8 @@ CHARSET_INFO *get_old_charset_by_name(co
 uchar* find_named(I_List<NAMED_LIST> *list, const char *name, uint length,
 		NAMED_LIST **found);
 
-extern sys_var_str sys_var_general_log_path, sys_var_slow_log_path;
+extern sys_var_str sys_var_general_log_path, sys_var_slow_log_path,
+       sys_var_backupdir;
 
 /* key_cache functions */
 KEY_CACHE *get_key_cache(LEX_STRING *cache_name);

=== modified file 'sql/share/errmsg.txt'
--- a/sql/share/errmsg.txt	2008-07-01 20:32:27 +0000
+++ b/sql/share/errmsg.txt	2008-07-02 19:37:44 +0000
@@ -6366,3 +6366,5 @@ ER_BACKUP_OBTAIN_NAME_LOCK_FAILED
 ER_BACKUP_RELEASE_NAME_LOCK_FAILED
   eng "Restore failed to release the name locks on the tables."
 
+ER_BACKUP_BACKUPDIR
+  eng "The path specified for the variable backupdir cannot be accessed or is invalid. ref: %-.64s"

=== modified file 'sql/unireg.h'
--- a/sql/unireg.h	2008-04-30 16:16:45 +0000
+++ b/sql/unireg.h	2008-07-02 19:37:44 +0000
@@ -32,6 +32,9 @@
 #ifndef DATADIR
 #define DATADIR		"data/"
 #endif
+#ifndef BACKUPDIR
+#define BACKUPDIR		"data/"
+#endif
 #ifndef SHAREDIR
 #define SHAREDIR	"share/"
 #endif

Thread
bzr commit into mysql-6.0-backup branch (cbell:2648) Bug#35230Chuck Bell2 Jul
  • Re: bzr commit into mysql-6.0-backup branch (cbell:2648) Bug#35230Rafal Somla7 Jul
    • RE: bzr commit into mysql-6.0-backup branch (cbell:2648) Bug#35230Chuck Bell8 Jul