From: Date: July 10 2008 4:01pm Subject: bzr commit into mysql-6.0-backup branch (cbell:2648) Bug#35230 List-Archive: http://lists.mysql.com/commits/49454 X-Bug: 35230 Message-Id: <200807101401.m6AE1c95028863@mail.mysql.com> MIME-Version: 1.0 Content-Type: text/plain; charset="us-ascii" Content-Transfer-Encoding: 7bit #At file:///D:/source/bzr/mysql-6.0-bug-35230/ 2648 Chuck Bell 2008-07-10 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. Note: Patch 1 of 2 containing changes to server code. Patch 2 is needed for complete implement. modified: mysql-test/r/backup_progress.result mysql-test/t/backup_progress.test sql/mysqld.cc sql/set_var.cc sql/set_var.h sql/share/errmsg.txt per-file messages: 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. 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. === 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-10 14:01:30 +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-10 14:01:30 +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 'sql/mysqld.cc' --- a/sql/mysqld.cc 2008-07-01 20:32:27 +0000 +++ b/sql/mysqld.cc 2008-07-10 14:01:30 +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,21 @@ 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))) + { + sql_print_warning("The path specified for the variable backupdir cannot" + " be accessed or is invalid. ref:'%s'\n", argument); + } + sys_var_backupdir.value= my_strdup(argument, MYF(0)); + 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) */ @@ -8561,6 +8579,16 @@ static void fix_paths(void) convert_dirname(language,language,NullS); (void) my_load_path(mysql_home,mysql_home,""); // Resolve current dir (void) my_load_path(mysql_real_data_home,mysql_real_data_home,mysql_home); + + /* + Set backupdir if datadir set on command line but not otherwise set. + */ + if (!sys_var_backupdir.value) + { + sys_var_backupdir.value= my_strdup(mysql_real_data_home, MYF(0)); + sys_var_backupdir.value_length= strlen(mysql_real_data_home); + } + (void) my_load_path(pidfile_name,pidfile_name,mysql_real_data_home); (void) my_load_path(opt_plugin_dir, opt_plugin_dir_ptr ? opt_plugin_dir_ptr : get_relative_path(PLUGINDIR), mysql_home); === 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-10 14:01:30 +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-10 14:01:30 +0000 @@ -1345,7 +1345,8 @@ CHARSET_INFO *get_old_charset_by_name(co uchar* find_named(I_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-10 14:01:30 +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 system variable backupdir cannot be accessed or is invalid. ref: %-.64s"