@@ -55,6 +55,7 @@ Place, Suite 330, Boston, MA 02111-1307 USA
5555#include  " common.h" 
5656#include  " backup_copy.h" 
5757#include  " backup_mysql.h" 
58+ #include  < regex.h> /*  for TokuDB log name */ 
5859
5960
6061/*  list of files to sync for --rsync mode */ 
@@ -408,6 +409,45 @@ datadir_iter_next(datadir_iter_t *it, datadir_node_t *node)
408409	return (ret);
409410}
410411
412+ /* ***********************************************************************
413+ Get next TokuDB file in datadir. 
414+ TokuDB data and log files are both put in datadir, not under database dir(like 
415+ InnoDB or MyISAM), so we add this new function alternative to 
416+ datadir_iter_next(). Maybe in future, TokuDB data files will put in database 
417+ dir, we'll remove this function. */  
418+ static 
419+ bool 
420+ datadir_iter_next_tokudb (datadir_iter_t  *it, datadir_node_t  *node)
421+ {
422+ 
423+ 	while  (fil_file_readdir_next_file (&it->err , it->datadir_path ,
424+ 					  it->dir , &it->dbinfo ) == 0 ) {
425+ 
426+ 		/*  TokuDB data and log files are both FILE type, and
427+ 		 we don't need DIR. */  
428+ 		if  (it->dbinfo .type  == OS_FILE_TYPE_DIR
429+ 		    || it->dbinfo .type  == OS_FILE_TYPE_UNKNOWN) {
430+ 			continue ;
431+ 		}
432+ 
433+ 		/*  We found a symlink or a file */ 
434+ 		make_path_n (2 , &it->filepath , &it->filepath_len ,
435+ 			  it->datadir_path , it->dbinfo .name );
436+ 		make_path_n (1 , &it->filepath_rel , &it->filepath_rel_len ,
437+ 			  it->dbinfo .name );
438+ 
439+ 		it->is_file  = true ;
440+ 		it->is_empty_dir  = false ;
441+ 
442+ 		datadir_node_fill (node, it);
443+ 
444+ 		return (true );
445+ 	}
446+ 
447+ 	/*  datadir iterate finished */ 
448+ 	return (false );
449+ }
450+ 
411451/* ***********************************************************************
412452Interface to read MySQL data file sequentially. One should open file 
413453with datafile_open to get cursor and close the cursor with 
@@ -750,6 +790,31 @@ filename_matches(const char *filename, const char **ext_list)
750790	return (false );
751791}
752792
793+ /* ***********************************************************************
794+ Check if file name matches given set of Regular Expressions 
795+ @return true if match. */  
796+ static 
797+ bool 
798+ filename_matches_regex (const  char  *filename, const  char  **pattern_list)
799+ {
800+ 	regex_t  re;
801+ 	const  char  **pattern;
802+ 
803+ 	for  (pattern = pattern_list; *pattern; pattern++) {
804+ 		regcomp (&re, *pattern, REG_EXTENDED|REG_NOSUB);
805+ 
806+ 		/*  match found */ 
807+ 		if  (regexec (&re, filename, 0 , NULL , 0 ) == 0 ) {
808+ 			regfree (&re);
809+ 			return (true );
810+ 		}
811+ 
812+ 		/*  re must be freed before next compile */ 
813+ 		regfree (&re);
814+ 	}
815+ 
816+ 	return (false );
817+ }
753818
754819/* ***********************************************************************
755820Copy data file for backup. Also check if it is allowed to copy by 
@@ -1281,9 +1346,90 @@ backup_files(const char *from, bool prep_mode)
12811346	return (ret);
12821347}
12831348
1349+ bool 
1350+ backup_tokudb_log_files (const  char  *from)
1351+ {
1352+ 	bool  ret = true ;
1353+ 	datadir_iter_t  *it;
1354+ 	datadir_node_t  node;
1355+ 	const  char  *pattern_list[] = {" .*\\ .tokulog[[:digit:]]+$" /*  redo log */ 
1356+ 				      " .*\\ .directory" /*  table dictionary */ 
1357+ 				      " .*\\ .rollback" /*  undo log */ 
1358+ 				      " .*\\ .environment" /*  meta info */ 
1359+ 				      NULL };
1360+ 
1361+ 	/*  Must have TokuDB SE enabled. */ 
1362+ 	ut_ad (have_tokudb);
1363+ 
1364+ 	msg_ts (" Starting to backup TokuDB log files under '%s'\n " 
1365+ 
1366+ 	datadir_node_init (&node);
1367+ 	it = datadir_iter_new (from);
1368+ 
1369+ 	while  (datadir_iter_next_tokudb (it, &node)) {
1370+ 
1371+ 		if  (!filename_matches_regex (node.filepath , pattern_list)) {
1372+ 			continue ;
1373+ 		}
1374+ 
1375+ 		if  (!(ret = copy_file (ds_data, node.filepath , node.filepath , 1 ))) {
1376+ 			msg_ts (" Error: Failed to copy file %s\n " filepath );
1377+ 			goto  out;
1378+ 		}
1379+ 	}
1380+ 
1381+ 	msg_ts (" Finished backing up TokuDB log files\n " 
1382+ 
1383+ out:
1384+ 	datadir_iter_free (it);
1385+ 	datadir_node_free (&node);
1386+ 
1387+ 	return (ret);
1388+ }
1389+ 
1390+ bool 
1391+ backup_tokudb_data_files (const  char  *from)
1392+ {
1393+ 	bool  ret = true ;
1394+ 	datadir_iter_t  *it;
1395+ 	datadir_node_t  node;
1396+ 	const  char  *ext_list[] = {" tokudb" NULL };
1397+ 
1398+ 	/*  Must have TokuDB SE enabled. */ 
1399+ 	ut_ad (have_tokudb);
1400+ 
1401+ 	msg_ts (" Starting to backup TokuDB data files under '%s'\n " 
1402+ 
1403+ 	datadir_node_init (&node);
1404+ 	it = datadir_iter_new (from);
1405+ 
1406+ 	while  (datadir_iter_next_tokudb (it, &node)) {
1407+ 
1408+ 		if  (!filename_matches (node.filepath , ext_list)) {
1409+ 			continue ;
1410+ 		}
1411+ 
1412+ 		if  (!(ret = copy_file (ds_data, node.filepath , node.filepath , 1 ))) {
1413+ 			msg_ts (" Error: Failed to copy file %s\n " filepath );
1414+ 			goto  out;
1415+ 		}
1416+ 	}
1417+ 
1418+ 	msg_ts (" Finished backing up TokuDB data files\n " 
1419+ out:
1420+ 	datadir_iter_free (it);
1421+ 	datadir_node_free (&node);
1422+ 
1423+ 	return (ret);
1424+ }
1425+ 
12841426bool 
12851427backup_start ()
12861428{
1429+ 	if  (have_tokudb) {
1430+ 		lock_tokudb_checkpoint (mysql_connection);
1431+ 	}
1432+ 
12871433	if  (!opt_no_lock) {
12881434		if  (opt_safe_slave_backup) {
12891435			if  (!wait_for_safe_slave (mysql_connection)) {
@@ -1350,6 +1496,24 @@ backup_start()
13501496			" FLUSH NO_WRITE_TO_BINLOG ENGINE LOGS" false );
13511497	}
13521498
1499+ 	if  (have_tokudb) {
1500+ 
1501+ 		if  (!strcmp (fil_path_to_mysql_datadir,
1502+ 			    tokudb_log_path_to_mysql_datadir)) {
1503+ 
1504+ 			/*  tokudb_log_dir and datadir are same dir */ 
1505+ 			if  (!backup_tokudb_log_files (fil_path_to_mysql_datadir))
1506+ 				return (false );
1507+ 		}
1508+ 		else  {
1509+ 
1510+ 			/*  tokudb_log_dir and datadir are different dir */ 
1511+ 			if  (!backup_tokudb_log_files (fil_path_to_mysql_datadir) ||
1512+ 			    !backup_tokudb_log_files (tokudb_log_path_to_mysql_datadir))
1513+ 				return (false );
1514+ 		}
1515+ 	}
1516+ 
13531517	return (true );
13541518}
13551519
@@ -1384,6 +1548,14 @@ backup_finish()
13841548		}
13851549	}
13861550
1551+ 	/*  Backup TokuDB data files */ 
1552+ 	if  (have_tokudb) {
1553+ 		if (!backup_tokudb_data_files (tokudb_data_path_to_mysql_datadir)) {
1554+ 			return (false );
1555+ 		}
1556+ 		unlock_tokudb_checkpoint (mysql_connection);
1557+ 	}
1558+ 
13871559	msg_ts (" Backup created in directory '%s'\n " 
13881560	if  (mysql_binlog_position != NULL ) {
13891561		msg (" MySQL binlog position: %s\n " 
0 commit comments