@@ -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 " , from);
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 " , node.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 " , from);
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 " , node.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 " , xtrabackup_target_dir);
13881560 if (mysql_binlog_position != NULL ) {
13891561 msg (" MySQL binlog position: %s\n " , mysql_binlog_position);
0 commit comments