mirror of
https://github.com/MariaDB/server.git
synced 2025-01-29 02:05:57 +01:00
Merge 10.1 into 10.2
Also, include fixes by Vladislav Vaintroub to the aws_key_management plugin. The AWS C++ SDK specifically depends on OPENSSL_LIBRARIES, not generic SSL_LIBRARIES (such as YaSSL).
This commit is contained in:
commit
14c6f00a9f
217 changed files with 30599 additions and 1665 deletions
7
.gitignore
vendored
7
.gitignore
vendored
|
@ -49,6 +49,8 @@ extra/comp_err
|
|||
extra/innochecksum
|
||||
extra/jemalloc/build/
|
||||
extra/jemalloc/tmp/
|
||||
extra/mariabackup/mariabackup
|
||||
extra/mariabackup/mbstream
|
||||
extra/my_print_defaults
|
||||
extra/mysql_waitpid
|
||||
extra/mysqld_safe_helper
|
||||
|
@ -124,6 +126,7 @@ scripts/mytop
|
|||
scripts/wsrep_sst_common
|
||||
scripts/wsrep_sst_mysqldump
|
||||
scripts/wsrep_sst_rsync
|
||||
scripts/wsrep_sst_mariabackup
|
||||
scripts/wsrep_sst_xtrabackup
|
||||
scripts/wsrep_sst_xtrabackup-v2
|
||||
scripts/maria_add_gis_sp.sql
|
||||
|
@ -248,6 +251,10 @@ storage/mroonga/vendor/groonga/src/groonga-benchmark
|
|||
storage/mroonga/vendor/groonga/src/suggest/groonga-suggest-create-dataset
|
||||
storage/mroonga/mysql-test/mroonga/storage/r/information_schema_plugins.result
|
||||
storage/mroonga/mysql-test/mroonga/storage/r/variable_version.result
|
||||
xxx/*
|
||||
yyy/*
|
||||
zzz/*
|
||||
|
||||
# C and C++
|
||||
|
||||
# Compiled Object files
|
||||
|
|
|
@ -3370,6 +3370,12 @@ void do_exec(struct st_command *command)
|
|||
#endif
|
||||
#endif
|
||||
|
||||
if (disable_result_log)
|
||||
{
|
||||
/* Collect stderr output as well, for the case app. crashes or returns error.*/
|
||||
dynstr_append(&ds_cmd, " 2>&1");
|
||||
}
|
||||
|
||||
DBUG_PRINT("info", ("Executing '%s' as '%s'",
|
||||
command->first_argument, ds_cmd.str));
|
||||
|
||||
|
@ -3405,16 +3411,7 @@ void do_exec(struct st_command *command)
|
|||
len--;
|
||||
}
|
||||
#endif
|
||||
if (disable_result_log)
|
||||
{
|
||||
if (len)
|
||||
buf[len-1] = 0;
|
||||
DBUG_PRINT("exec_result",("%s", buf));
|
||||
}
|
||||
else
|
||||
{
|
||||
replace_dynstr_append_mem(ds_result, buf, len);
|
||||
}
|
||||
replace_dynstr_append_mem(ds_result, buf, len);
|
||||
}
|
||||
error= pclose(res_file);
|
||||
|
||||
|
@ -3424,7 +3421,7 @@ void do_exec(struct st_command *command)
|
|||
dynstr_free(&ds_sorted);
|
||||
}
|
||||
|
||||
if (error > 0)
|
||||
if (error)
|
||||
{
|
||||
uint status= WEXITSTATUS(error);
|
||||
int i;
|
||||
|
@ -3470,6 +3467,12 @@ void do_exec(struct st_command *command)
|
|||
}
|
||||
|
||||
dynstr_free(&ds_cmd);
|
||||
|
||||
if (disable_result_log)
|
||||
{
|
||||
/* Disable output in case of successful exit.*/
|
||||
dynstr_set(&ds_res,"");
|
||||
}
|
||||
DBUG_VOID_RETURN;
|
||||
}
|
||||
|
||||
|
@ -3607,6 +3610,37 @@ void do_system(struct st_command *command)
|
|||
}
|
||||
|
||||
|
||||
/* returns TRUE if path is inside a sandbox */
|
||||
bool is_sub_path(const char *path, size_t plen, const char *sandbox)
|
||||
{
|
||||
size_t len= strlen(sandbox);
|
||||
if (!sandbox || !len || plen <= len || memcmp(path, sandbox, len - 1)
|
||||
|| path[len] != '/')
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
/* returns TRUE if path cannot be modified */
|
||||
bool bad_path(const char *path)
|
||||
{
|
||||
size_t plen= strlen(path);
|
||||
|
||||
const char *vardir= getenv("MYSQLTEST_VARDIR");
|
||||
if (is_sub_path(path, plen, vardir))
|
||||
return false;
|
||||
|
||||
const char *tmpdir= getenv("MYSQL_TMP_DIR");
|
||||
if (is_sub_path(path, plen, tmpdir))
|
||||
return false;
|
||||
|
||||
report_or_die("Path '%s' is not a subdirectory of MYSQLTEST_VARDIR '%s'"
|
||||
"or MYSQL_TMP_DIR '%s'",
|
||||
path, vardir, tmpdir);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
SYNOPSIS
|
||||
set_wild_chars
|
||||
|
@ -3665,6 +3699,9 @@ void do_remove_file(struct st_command *command)
|
|||
rm_args, sizeof(rm_args)/sizeof(struct command_arg),
|
||||
' ');
|
||||
|
||||
if (bad_path(ds_filename.str))
|
||||
DBUG_VOID_RETURN;
|
||||
|
||||
DBUG_PRINT("info", ("removing file: %s", ds_filename.str));
|
||||
error= my_delete(ds_filename.str, MYF(disable_warnings ? 0 : MY_WME)) != 0;
|
||||
handle_command_error(command, error, my_errno);
|
||||
|
@ -3708,6 +3745,9 @@ void do_remove_files_wildcard(struct st_command *command)
|
|||
' ');
|
||||
fn_format(dirname, ds_directory.str, "", "", MY_UNPACK_FILENAME);
|
||||
|
||||
if (bad_path(ds_directory.str))
|
||||
DBUG_VOID_RETURN;
|
||||
|
||||
DBUG_PRINT("info", ("listing directory: %s", dirname));
|
||||
if (!(dir_info= my_dir(dirname, MYF(MY_DONT_SORT | MY_WANT_STAT | MY_WME))))
|
||||
{
|
||||
|
@ -3782,6 +3822,9 @@ void do_copy_file(struct st_command *command)
|
|||
sizeof(copy_file_args)/sizeof(struct command_arg),
|
||||
' ');
|
||||
|
||||
if (bad_path(ds_to_file.str))
|
||||
DBUG_VOID_RETURN;
|
||||
|
||||
DBUG_PRINT("info", ("Copy %s to %s", ds_from_file.str, ds_to_file.str));
|
||||
/* MY_HOLD_ORIGINAL_MODES prevents attempts to chown the file */
|
||||
error= (my_copy(ds_from_file.str, ds_to_file.str,
|
||||
|
@ -3819,6 +3862,9 @@ void do_move_file(struct st_command *command)
|
|||
sizeof(move_file_args)/sizeof(struct command_arg),
|
||||
' ');
|
||||
|
||||
if (bad_path(ds_to_file.str))
|
||||
DBUG_VOID_RETURN;
|
||||
|
||||
DBUG_PRINT("info", ("Move %s to %s", ds_from_file.str, ds_to_file.str));
|
||||
error= (my_rename(ds_from_file.str, ds_to_file.str,
|
||||
MYF(disable_warnings ? 0 : MY_WME)) != 0);
|
||||
|
@ -3857,6 +3903,9 @@ void do_chmod_file(struct st_command *command)
|
|||
sizeof(chmod_file_args)/sizeof(struct command_arg),
|
||||
' ');
|
||||
|
||||
if (bad_path(ds_file.str))
|
||||
DBUG_VOID_RETURN;
|
||||
|
||||
/* Parse what mode to set */
|
||||
if (ds_mode.length != 4 ||
|
||||
str2int(ds_mode.str, 8, 0, INT_MAX, &mode) == NullS)
|
||||
|
@ -3928,6 +3977,9 @@ void do_mkdir(struct st_command *command)
|
|||
mkdir_args, sizeof(mkdir_args)/sizeof(struct command_arg),
|
||||
' ');
|
||||
|
||||
if (bad_path(ds_dirname.str))
|
||||
DBUG_VOID_RETURN;
|
||||
|
||||
DBUG_PRINT("info", ("creating directory: %s", ds_dirname.str));
|
||||
error= my_mkdir(ds_dirname.str, 0777, MYF(MY_WME)) != 0;
|
||||
handle_command_error(command, error, my_errno);
|
||||
|
@ -3935,6 +3987,47 @@ void do_mkdir(struct st_command *command)
|
|||
DBUG_VOID_RETURN;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
Remove directory recursively.
|
||||
*/
|
||||
static int rmtree(const char *dir)
|
||||
{
|
||||
char path[FN_REFLEN];
|
||||
char sep[]={ FN_LIBCHAR, 0 };
|
||||
int err=0;
|
||||
|
||||
MY_DIR *dir_info= my_dir(dir, MYF(MY_DONT_SORT | MY_WANT_STAT));
|
||||
if (!dir_info)
|
||||
return 1;
|
||||
|
||||
for (uint i= 0; i < dir_info->number_of_files; i++)
|
||||
{
|
||||
FILEINFO *file= dir_info->dir_entry + i;
|
||||
/* Skip "." and ".." */
|
||||
if (!strcmp(file->name, ".") || !strcmp(file->name, ".."))
|
||||
continue;
|
||||
|
||||
strxnmov(path, sizeof(path), dir, sep, file->name, NULL);
|
||||
|
||||
if (!MY_S_ISDIR(file->mystat->st_mode))
|
||||
err= my_delete(path, 0);
|
||||
else
|
||||
err= rmtree(path);
|
||||
|
||||
if(err)
|
||||
break;
|
||||
}
|
||||
|
||||
my_dirend(dir_info);
|
||||
|
||||
if (!err)
|
||||
err= rmdir(dir);
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
SYNOPSIS
|
||||
do_rmdir
|
||||
|
@ -3942,12 +4035,11 @@ void do_mkdir(struct st_command *command)
|
|||
|
||||
DESCRIPTION
|
||||
rmdir <dir_name>
|
||||
Remove the empty directory <dir_name>
|
||||
Remove the directory tree
|
||||
*/
|
||||
|
||||
void do_rmdir(struct st_command *command)
|
||||
{
|
||||
int error;
|
||||
static DYNAMIC_STRING ds_dirname;
|
||||
const struct command_arg rmdir_args[] = {
|
||||
{ "dirname", ARG_STRING, TRUE, &ds_dirname, "Directory to remove" }
|
||||
|
@ -3958,9 +4050,13 @@ void do_rmdir(struct st_command *command)
|
|||
rmdir_args, sizeof(rmdir_args)/sizeof(struct command_arg),
|
||||
' ');
|
||||
|
||||
if (bad_path(ds_dirname.str))
|
||||
DBUG_VOID_RETURN;
|
||||
|
||||
DBUG_PRINT("info", ("removing directory: %s", ds_dirname.str));
|
||||
error= rmdir(ds_dirname.str) != 0;
|
||||
handle_command_error(command, error, errno);
|
||||
if (rmtree(ds_dirname.str))
|
||||
handle_command_error(command, 1, errno);
|
||||
|
||||
dynstr_free(&ds_dirname);
|
||||
DBUG_VOID_RETURN;
|
||||
}
|
||||
|
@ -4073,6 +4169,9 @@ static void do_list_files_write_file_command(struct st_command *command,
|
|||
list_files_args,
|
||||
sizeof(list_files_args)/sizeof(struct command_arg), ' ');
|
||||
|
||||
if (bad_path(ds_filename.str))
|
||||
DBUG_VOID_RETURN;
|
||||
|
||||
init_dynamic_string(&ds_content, "", 1024, 1024);
|
||||
error= get_list_files(&ds_content, &ds_dirname, &ds_wild);
|
||||
handle_command_error(command, error, my_errno);
|
||||
|
@ -4124,7 +4223,8 @@ void read_until_delimiter(DYNAMIC_STRING *ds,
|
|||
while (1)
|
||||
{
|
||||
c= my_getc(cur_file->file);
|
||||
|
||||
if (c == '\r')
|
||||
c= my_getc(cur_file->file);
|
||||
if (c == '\n')
|
||||
{
|
||||
cur_file->lineno++;
|
||||
|
@ -4175,6 +4275,9 @@ void do_write_file_command(struct st_command *command, my_bool append)
|
|||
sizeof(write_file_args)/sizeof(struct command_arg),
|
||||
' ');
|
||||
|
||||
if (bad_path(ds_filename.str))
|
||||
DBUG_VOID_RETURN;
|
||||
|
||||
if (!append && access(ds_filename.str, F_OK) == 0)
|
||||
{
|
||||
/* The file should not be overwritten */
|
||||
|
|
|
@ -88,20 +88,24 @@ ENDIF()
|
|||
OPTION(ENABLED_LOCAL_INFILE "" ON)
|
||||
SET(WITH_INNODB_SNAPPY OFF CACHE STRING "")
|
||||
IF(WIN32)
|
||||
SET(WITH_LIBARCHIVE STATIC CACHE STRING "")
|
||||
ELSEIF(RPM)
|
||||
SET(WITH_SSL system CACHE STRING "")
|
||||
SET(WITH_ZLIB system CACHE STRING "")
|
||||
SET(CHECKMODULE /usr/bin/checkmodule CACHE STRING "")
|
||||
SET(SEMODULE_PACKAGE /usr/bin/semodule_package CACHE STRING "")
|
||||
SET(WITH_LIBARCHIVE ON CACHE STRING "")
|
||||
ELSEIF(DEB)
|
||||
SET(WITH_SSL system CACHE STRING "")
|
||||
SET(WITH_ZLIB system CACHE STRING "")
|
||||
SET(WITH_LIBWRAP ON)
|
||||
SET(HAVE_EMBEDDED_PRIVILEGE_CONTROL ON)
|
||||
SET(WITH_LIBARCHIVE ON CACHE STRING "")
|
||||
ELSE()
|
||||
SET(WITH_SSL bundled CACHE STRING "")
|
||||
SET(WITH_ZLIB bundled CACHE STRING "")
|
||||
SET(WITH_JEMALLOC static CACHE STRING "")
|
||||
SET(WITH_LIBARCHIVE STATIC CACHE STRING "")
|
||||
ENDIF()
|
||||
|
||||
IF(NOT COMPILATION_COMMENT)
|
||||
|
|
|
@ -23,10 +23,14 @@ SET(CPACK_COMPONENT_SHAREDLIBRARIES_GROUP "shared")
|
|||
SET(CPACK_COMPONENT_COMMON_GROUP "common")
|
||||
SET(CPACK_COMPONENT_CLIENTPLUGINS_GROUP "common")
|
||||
SET(CPACK_COMPONENT_COMPAT_GROUP "compat")
|
||||
SET(CPACK_COMPONENT_BACKUP_GROUP "backup")
|
||||
|
||||
SET(CPACK_COMPONENTS_ALL Server ManPagesServer IniFiles Server_Scripts
|
||||
SupportFiles Development ManPagesDevelopment
|
||||
ManPagesTest Readme ManPagesClient Test
|
||||
Common Client SharedLibraries ClientPlugins)
|
||||
Common Client SharedLibraries ClientPlugins
|
||||
backup
|
||||
)
|
||||
|
||||
SET(CPACK_RPM_PACKAGE_NAME ${CPACK_PACKAGE_NAME})
|
||||
SET(CPACK_PACKAGE_FILE_NAME "${CPACK_RPM_PACKAGE_NAME}-${VERSION}-${RPM}-${CMAKE_SYSTEM_PROCESSOR}")
|
||||
|
@ -112,6 +116,7 @@ SET(CPACK_RPM_client_USER_FILELIST ${ignored} "%config(noreplace) ${INSTALL_SYSC
|
|||
SET(CPACK_RPM_compat_USER_FILELIST ${ignored})
|
||||
SET(CPACK_RPM_devel_USER_FILELIST ${ignored})
|
||||
SET(CPACK_RPM_test_USER_FILELIST ${ignored})
|
||||
SET(CPACK_RPM_backup_USER_FILELIST ${ignored})
|
||||
|
||||
# "set/append array" - append a set of strings, separated by a space
|
||||
MACRO(SETA var)
|
||||
|
|
|
@ -201,13 +201,15 @@ MACRO(MYSQL_ADD_PLUGIN)
|
|||
# executable to the linker command line (it would result into link error).
|
||||
# Thus we skip TARGET_LINK_LIBRARIES on Linux, as it would only generate
|
||||
# an additional dependency.
|
||||
IF(NOT ARG_CLIENT)
|
||||
IF(ARG_RECOMPILE_FOR_EMBEDDED OR ARG_STORAGE_ENGINE)
|
||||
IF(MSVC)
|
||||
ADD_DEPENDENCIES(${target} gen_mysqld_lib)
|
||||
TARGET_LINK_LIBRARIES(${target} mysqld_import_lib)
|
||||
ELSEIF(NOT CMAKE_SYSTEM_NAME STREQUAL "Linux")
|
||||
TARGET_LINK_LIBRARIES (${target} mysqld)
|
||||
ENDIF()
|
||||
ELSEIF(CMAKE_SYSTEM_NAME STREQUAL "Linux" AND NOT WITH_ASAN)
|
||||
TARGET_LINK_LIBRARIES (${target} "-Wl,--no-undefined")
|
||||
ENDIF()
|
||||
|
||||
ADD_DEPENDENCIES(${target} GenError ${ARG_DEPENDENCIES})
|
||||
|
|
2
debian/control
vendored
2
debian/control
vendored
|
@ -622,4 +622,4 @@ Description: MariaDB database regression test suite - data files
|
|||
language in the world. The main goals of MariaDB are speed, robustness and
|
||||
ease of use.
|
||||
.
|
||||
This package has the architecture independent data files for the test suite.
|
||||
This package has the architecture independent data files for the test suite.
|
2
debian/mariadb-backup-10.1.files
vendored
Normal file
2
debian/mariadb-backup-10.1.files
vendored
Normal file
|
@ -0,0 +1,2 @@
|
|||
usr/bin/mariabackup
|
||||
usr/bin/mbstream
|
1
debian/mariadb-server-10.2.install
vendored
1
debian/mariadb-server-10.2.install
vendored
|
@ -38,6 +38,7 @@ usr/bin/wsrep_sst_mysqldump
|
|||
usr/bin/wsrep_sst_rsync
|
||||
usr/bin/wsrep_sst_xtrabackup
|
||||
usr/bin/wsrep_sst_xtrabackup-v2
|
||||
usr/bin/wsrep_sst_mariabackup
|
||||
usr/lib/mysql/plugin/auth_pam.so
|
||||
usr/lib/mysql/plugin/auth_socket.so
|
||||
usr/lib/mysql/plugin/file_key_management.so
|
||||
|
|
214
extra/mariabackup/CMakeLists.txt
Normal file
214
extra/mariabackup/CMakeLists.txt
Normal file
|
@ -0,0 +1,214 @@
|
|||
# Copyright (c) 2013, 2017 Percona LLC and/or its affiliates.
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation; version 2 of the License.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program; if not, write to the Free Software
|
||||
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
|
||||
|
||||
|
||||
OPTION(WITH_MARIABACKUP "Include mariabackup" ON)
|
||||
IF(NOT WITH_MARIABACKUP)
|
||||
RETURN()
|
||||
ENDIF()
|
||||
|
||||
|
||||
IF(NOT WIN32)
|
||||
CHECK_SYMBOL_EXISTS(regcomp regex.h HAVE_SYSTEM_REGEX)
|
||||
IF(HAVE_SYSTEM_REGEX)
|
||||
ADD_DEFINITIONS(-DHAVE_SYSTEM_REGEX)
|
||||
ENDIF()
|
||||
ENDIF()
|
||||
|
||||
IF(WITH_LIBARCHIVE STREQUAL "STATIC")
|
||||
SET(CMAKE_FIND_LIBRARY_SUFFIXES .a .lib)
|
||||
ENDIF()
|
||||
|
||||
FIND_PACKAGE(LibArchive)
|
||||
|
||||
IF(NOT DEFINED WITH_LIBARCHIVE)
|
||||
IF(LibArchive_FOUND)
|
||||
SET(WITH_LIBARCHIVE_DEFAULT ON)
|
||||
ELSE()
|
||||
SET(WITH_LIBARCHIVE_DEFAULT OFF)
|
||||
ENDIF()
|
||||
SET(WITH_LIBARCHIVE ${WITH_LIBARCHIVE_DEFAULT} CACHE STRING "Use libarchive for streaming features (ON, OFF or STATIC)" )
|
||||
ENDIF()
|
||||
|
||||
IF(NOT WITH_LIBARCHIVE MATCHES "^(ON|OFF|STATIC)$")
|
||||
MESSAGE(FATAL_ERROR "Invalid value for WITH_LIBARCHIVE: '${WITH_LIBARCHIVE}'. Use one of ON, OFF or STATIC")
|
||||
ENDIF()
|
||||
|
||||
IF(UNIX)
|
||||
SET(PIC_FLAG -fPIC)
|
||||
ENDIF()
|
||||
|
||||
IF((NOT WITH_LIBARCHIVE STREQUAL "OFF") AND (NOT LibArchive_FOUND))
|
||||
IF(CMAKE_VERSION VERSION_LESS "2.8.12")
|
||||
MESSAGE("libarchive can't be built, old cmake")
|
||||
ELSE()
|
||||
# Build a local version
|
||||
INCLUDE(ExternalProject)
|
||||
SET(LIBARCHIVE_DIR ${CMAKE_CURRENT_BINARY_DIR}/libarchive)
|
||||
SET(libarchive_PREFIX ${CMAKE_CURRENT_BINARY_DIR}/libarchive)
|
||||
SET(libarchive_CMAKE_ARGS
|
||||
-DCMAKE_INSTALL_PREFIX:PATH=<INSTALL_DIR>
|
||||
-DCMAKE_BUILD_TYPE=${CMAKE_BUILD_TYPE}
|
||||
-DENABLE_ICONV=OFF
|
||||
-DENABLE_TAR=ON
|
||||
-DENABLE_OPENSSL=OFF
|
||||
-DENABLE_TEST=OFF
|
||||
"-DCMAKE_C_FLAGS_DEBUG=${CMAKE_C_FLAGS_DEBUG} ${PIC_FLAG}"
|
||||
"-DCMAKE_C_FLAGS_RELWITHDEBINFO=${CMAKE_C_FLAGS_RELWITHDEBINFO} ${PIC_FLAG}"
|
||||
"-DCMAKE_C_FLAGS_RELEASE=${CMAKE_C_FLAGS_RELEASE} ${PIC_FLAG}"
|
||||
"-DCMAKE_C_FLAGS_MINSIZEREL=${CMAKE_C_FLAGS_MINSIZEREL} ${PIC_FLAG}"
|
||||
)
|
||||
IF(WIN32)
|
||||
SET(libarchive_CMAKE_ARGS ${libarchive_CMAKE_ARGS} -DWINDOWS_VERSION=WIN7 -DCMAKE_DEBUG_POSTFIX=d)
|
||||
SET(LIBARCHIVE_RELEASE_LIB ${LIBARCHIVE_DIR}/lib/${CMAKE_STATIC_LIBRARY_PREFIX}archive_static${CMAKE_STATIC_LIBRARY_SUFFIX})
|
||||
SET(LIBARCHIVE_DEBUG_LIB ${LIBARCHIVE_DIR}/lib/${CMAKE_STATIC_LIBRARY_PREFIX}archive_staticd${CMAKE_STATIC_LIBRARY_SUFFIX})
|
||||
SET(byproducts ${LIBARCHIVE_RELEASE_LIB} ${LIBARCHIVE_DEBUG_LIB})
|
||||
ELSE()
|
||||
SET(LIBARCHIVE_LIB ${LIBARCHIVE_DIR}/lib/${CMAKE_STATIC_LIBRARY_PREFIX}archive${CMAKE_STATIC_LIBRARY_SUFFIX})
|
||||
SET(byproducts ${LIBARCHIVE_LIB})
|
||||
ENDIF()
|
||||
|
||||
IF(CMAKE_VERSION VERSION_GREATER "3.1")
|
||||
SET(byproducts BUILD_BYPRODUCTS ${byproducts})
|
||||
ENDIF()
|
||||
|
||||
ExternalProject_Add(libarchive
|
||||
PREFIX ${libarchive_PREFIX}
|
||||
DOWNLOAD_DIR ${LIBARCHIVE_DIR}
|
||||
URL http://www.libarchive.org/downloads/libarchive-3.2.2.tar.gz
|
||||
INSTALL_DIR ${LIBARCHIVE_DIR}
|
||||
CMAKE_ARGS ${libarchive_CMAKE_ARGS}
|
||||
${byproducts}
|
||||
)
|
||||
ADD_LIBRARY(archive_static STATIC IMPORTED)
|
||||
ADD_DEPENDENCIES(archive_static libarchive)
|
||||
IF(WIN32)
|
||||
SET_PROPERTY(TARGET archive_static PROPERTY IMPORTED_LOCATION_RELWITHDEBINFO ${LIBARCHIVE_RELEASE_LIB})
|
||||
SET_PROPERTY(TARGET archive_static PROPERTY IMPORTED_LOCATION_RELEASE ${LIBARCHIVE_RELEASE_LIB})
|
||||
SET_PROPERTY(TARGET archive_static PROPERTY IMPORTED_LOCATION_DEBUG ${LIBARCHIVE_DEBUG_LIB})
|
||||
SET_PROPERTY(TARGET archive_static PROPERTY IMPORTED_LOCATION_MINSIZEREL ${LIBARCHIVE_RELEASE_LIB})
|
||||
ELSE()
|
||||
SET_PROPERTY(TARGET archive_static PROPERTY IMPORTED_LOCATION ${LIBARCHIVE_LIB})
|
||||
ENDIF()
|
||||
|
||||
SET(LibArchive_FOUND ON )
|
||||
SET(LibArchive_INCLUDE_DIRS ${LIBARCHIVE_DIR}/include )
|
||||
SET(LibArchive_LIBRARIES archive_static)
|
||||
IF(WIN32)
|
||||
SET(LIBARCHIVE_STATIC 1)
|
||||
ENDIF()
|
||||
ENDIF()
|
||||
ENDIF()
|
||||
|
||||
|
||||
IF(WITH_LIBARCHIVE AND LibArchive_FOUND)
|
||||
ADD_DEFINITIONS(-DHAVE_LIBARCHIVE)
|
||||
IF(LIBARCHIVE_STATIC)
|
||||
ADD_DEFINITIONS(-DLIBARCHIVE_STATIC)
|
||||
ENDIF()
|
||||
INCLUDE_DIRECTORIES(${LibArchive_INCLUDE_DIRS})
|
||||
LINK_LIBRARIES(${LibArchive_LIBRARIES})
|
||||
SET(DS_ARCHIVE_SOURCE ds_archive.c)
|
||||
ENDIF()
|
||||
|
||||
INCLUDE_DIRECTORIES(
|
||||
${CMAKE_SOURCE_DIR}/include
|
||||
${CMAKE_SOURCE_DIR}/storage/xtradb/include
|
||||
${CMAKE_SOURCE_DIR}/sql
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/quicklz
|
||||
${CMAKE_CURRENT_SOURCE_DIR}
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/crc
|
||||
)
|
||||
|
||||
IF(NOT HAVE_SYSTEM_REGEX)
|
||||
INCLUDE_DIRECTORIES(${CMAKE_SOURCE_DIR}/pcre)
|
||||
ENDIF()
|
||||
|
||||
ADD_DEFINITIONS(-UMYSQL_SERVER)
|
||||
########################################################################
|
||||
# xtrabackup binary
|
||||
########################################################################
|
||||
|
||||
IF(WIN32)
|
||||
SET(NT_SERVICE_SOURCE ${PROJECT_SOURCE_DIR}/sql/nt_servc.cc)
|
||||
ELSE()
|
||||
SET(NT_SERVICE_SOURCE)
|
||||
ENDIF()
|
||||
|
||||
ADD_DEFINITIONS(-DPCRE_STATIC=1)
|
||||
|
||||
MYSQL_ADD_EXECUTABLE(mariabackup
|
||||
xtrabackup.cc
|
||||
innobackupex.cc
|
||||
changed_page_bitmap.cc
|
||||
datasink.c
|
||||
${DS_ARCHIVE_SOURCE}
|
||||
ds_buffer.c
|
||||
ds_compress.c
|
||||
ds_local.c
|
||||
ds_stdout.c
|
||||
ds_tmpfile.c
|
||||
ds_xbstream.c
|
||||
fil_cur.cc
|
||||
quicklz/quicklz.c
|
||||
read_filt.cc
|
||||
write_filt.cc
|
||||
wsrep.cc
|
||||
xbstream_write.c
|
||||
backup_mysql.cc
|
||||
backup_copy.cc
|
||||
encryption_plugin.cc
|
||||
${PROJECT_SOURCE_DIR}/libmysql/libmysql.c
|
||||
${PROJECT_SOURCE_DIR}/sql/net_serv.cc
|
||||
${NT_SERVICE_SOURCE}
|
||||
COMPONENT backup
|
||||
)
|
||||
|
||||
|
||||
# Export all symbols on Unix, for better crash callstacks
|
||||
SET_TARGET_PROPERTIES(mariabackup PROPERTIES ENABLE_EXPORTS TRUE)
|
||||
ADD_SUBDIRECTORY(crc)
|
||||
|
||||
|
||||
TARGET_LINK_LIBRARIES(mariabackup sql crc)
|
||||
|
||||
IF(NOT HAVE_SYSTEM_REGEX)
|
||||
TARGET_LINK_LIBRARIES(mariabackup pcreposix)
|
||||
ENDIF()
|
||||
|
||||
|
||||
########################################################################
|
||||
# xbstream binary
|
||||
########################################################################
|
||||
MYSQL_ADD_EXECUTABLE(mbstream
|
||||
ds_buffer.c
|
||||
ds_local.c
|
||||
ds_stdout.c
|
||||
datasink.c
|
||||
xbstream.c
|
||||
xbstream_read.c
|
||||
xbstream_write.c
|
||||
COMPONENT backup
|
||||
)
|
||||
|
||||
|
||||
TARGET_LINK_LIBRARIES(mbstream
|
||||
mysys
|
||||
crc
|
||||
)
|
||||
|
||||
IF(MSVC)
|
||||
SET_TARGET_PROPERTIES(mbstream PROPERTIES LINK_FLAGS setargv.obj)
|
||||
ENDIF()
|
2075
extra/mariabackup/backup_copy.cc
Normal file
2075
extra/mariabackup/backup_copy.cc
Normal file
File diff suppressed because it is too large
Load diff
49
extra/mariabackup/backup_copy.h
Normal file
49
extra/mariabackup/backup_copy.h
Normal file
|
@ -0,0 +1,49 @@
|
|||
|
||||
#ifndef XTRABACKUP_BACKUP_COPY_H
|
||||
#define XTRABACKUP_BACKUP_COPY_H
|
||||
|
||||
#include <my_global.h>
|
||||
#include "datasink.h"
|
||||
|
||||
/* special files */
|
||||
#define XTRABACKUP_SLAVE_INFO "xtrabackup_slave_info"
|
||||
#define XTRABACKUP_GALERA_INFO "xtrabackup_galera_info"
|
||||
#define XTRABACKUP_BINLOG_INFO "xtrabackup_binlog_info"
|
||||
#define XTRABACKUP_INFO "xtrabackup_info"
|
||||
|
||||
extern bool binlog_locked;
|
||||
|
||||
bool
|
||||
backup_file_printf(const char *filename, const char *fmt, ...)
|
||||
ATTRIBUTE_FORMAT(printf, 2, 0);
|
||||
|
||||
/************************************************************************
|
||||
Return true if first and second arguments are the same path. */
|
||||
bool
|
||||
equal_paths(const char *first, const char *second);
|
||||
|
||||
/************************************************************************
|
||||
Copy file for backup/restore.
|
||||
@return true in case of success. */
|
||||
bool
|
||||
copy_file(ds_ctxt_t *datasink,
|
||||
const char *src_file_path,
|
||||
const char *dst_file_path,
|
||||
uint thread_n);
|
||||
|
||||
bool
|
||||
backup_start();
|
||||
bool
|
||||
backup_finish();
|
||||
bool
|
||||
apply_log_finish();
|
||||
bool
|
||||
copy_back();
|
||||
bool
|
||||
decrypt_decompress();
|
||||
bool
|
||||
is_path_separator(char);
|
||||
bool
|
||||
directory_exists(const char *dir, bool create);
|
||||
|
||||
#endif
|
1648
extra/mariabackup/backup_mysql.cc
Normal file
1648
extra/mariabackup/backup_mysql.cc
Normal file
File diff suppressed because it is too large
Load diff
92
extra/mariabackup/backup_mysql.h
Normal file
92
extra/mariabackup/backup_mysql.h
Normal file
|
@ -0,0 +1,92 @@
|
|||
#ifndef XTRABACKUP_BACKUP_MYSQL_H
|
||||
#define XTRABACKUP_BACKUP_MYSQL_H
|
||||
|
||||
#include <mysql.h>
|
||||
|
||||
/* mysql flavor and version */
|
||||
enum mysql_flavor_t { FLAVOR_UNKNOWN, FLAVOR_MYSQL,
|
||||
FLAVOR_PERCONA_SERVER, FLAVOR_MARIADB };
|
||||
extern mysql_flavor_t server_flavor;
|
||||
extern unsigned long mysql_server_version;
|
||||
|
||||
/* server capabilities */
|
||||
extern bool have_changed_page_bitmaps;
|
||||
extern bool have_backup_locks;
|
||||
extern bool have_lock_wait_timeout;
|
||||
extern bool have_galera_enabled;
|
||||
extern bool have_flush_engine_logs;
|
||||
extern bool have_multi_threaded_slave;
|
||||
extern bool have_gtid_slave;
|
||||
|
||||
|
||||
/* History on server */
|
||||
extern time_t history_start_time;
|
||||
extern time_t history_end_time;
|
||||
extern time_t history_lock_time;
|
||||
|
||||
|
||||
extern bool sql_thread_started;
|
||||
extern char *mysql_slave_position;
|
||||
extern char *mysql_binlog_position;
|
||||
extern char *buffer_pool_filename;
|
||||
|
||||
/** connection to mysql server */
|
||||
extern MYSQL *mysql_connection;
|
||||
|
||||
void
|
||||
capture_tool_command(int argc, char **argv);
|
||||
|
||||
bool
|
||||
select_history();
|
||||
|
||||
bool
|
||||
flush_changed_page_bitmaps();
|
||||
|
||||
void
|
||||
backup_cleanup();
|
||||
|
||||
bool
|
||||
get_mysql_vars(MYSQL *connection);
|
||||
|
||||
bool
|
||||
detect_mysql_capabilities_for_backup();
|
||||
|
||||
MYSQL *
|
||||
xb_mysql_connect();
|
||||
|
||||
MYSQL_RES *
|
||||
xb_mysql_query(MYSQL *connection, const char *query, bool use_result,
|
||||
bool die_on_error = true);
|
||||
|
||||
void
|
||||
unlock_all(MYSQL *connection);
|
||||
|
||||
bool
|
||||
write_current_binlog_file(MYSQL *connection);
|
||||
|
||||
bool
|
||||
write_binlog_info(MYSQL *connection);
|
||||
|
||||
bool
|
||||
write_xtrabackup_info(MYSQL *connection);
|
||||
|
||||
bool
|
||||
write_backup_config_file();
|
||||
|
||||
bool
|
||||
lock_binlog_maybe(MYSQL *connection);
|
||||
|
||||
bool
|
||||
lock_tables(MYSQL *connection);
|
||||
|
||||
bool
|
||||
wait_for_safe_slave(MYSQL *connection);
|
||||
|
||||
bool
|
||||
write_galera_info(MYSQL *connection);
|
||||
|
||||
bool
|
||||
write_slave_info(MYSQL *connection);
|
||||
|
||||
|
||||
#endif
|
1018
extra/mariabackup/changed_page_bitmap.cc
Normal file
1018
extra/mariabackup/changed_page_bitmap.cc
Normal file
File diff suppressed because it is too large
Load diff
85
extra/mariabackup/changed_page_bitmap.h
Normal file
85
extra/mariabackup/changed_page_bitmap.h
Normal file
|
@ -0,0 +1,85 @@
|
|||
/******************************************************
|
||||
XtraBackup: hot backup tool for InnoDB
|
||||
(c) 2009-2012 Percona Inc.
|
||||
Originally Created 3/3/2009 Yasufumi Kinoshita
|
||||
Written by Alexey Kopytov, Aleksandr Kuzminsky, Stewart Smith, Vadim Tkachenko,
|
||||
Yasufumi Kinoshita, Ignacio Nin and Baron Schwartz.
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; version 2 of the License.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
|
||||
|
||||
*******************************************************/
|
||||
|
||||
/* Changed page bitmap interface */
|
||||
|
||||
#ifndef XB_CHANGED_PAGE_BITMAP_H
|
||||
#define XB_CHANGED_PAGE_BITMAP_H
|
||||
|
||||
#include <ut0rbt.h>
|
||||
#include <fil0fil.h>
|
||||
|
||||
/* The changed page bitmap structure */
|
||||
typedef ib_rbt_t xb_page_bitmap;
|
||||
|
||||
struct xb_page_bitmap_range_struct;
|
||||
|
||||
/* The bitmap range iterator over one space id */
|
||||
typedef struct xb_page_bitmap_range_struct xb_page_bitmap_range;
|
||||
|
||||
/****************************************************************//**
|
||||
Read the disk bitmap and build the changed page bitmap tree for the
|
||||
LSN interval incremental_lsn to checkpoint_lsn_start.
|
||||
|
||||
@return the built bitmap tree */
|
||||
xb_page_bitmap*
|
||||
xb_page_bitmap_init(void);
|
||||
/*=====================*/
|
||||
|
||||
/****************************************************************//**
|
||||
Free the bitmap tree. */
|
||||
void
|
||||
xb_page_bitmap_deinit(
|
||||
/*==================*/
|
||||
xb_page_bitmap* bitmap); /*!<in/out: bitmap tree */
|
||||
|
||||
|
||||
/****************************************************************//**
|
||||
Set up a new bitmap range iterator over a given space id changed
|
||||
pages in a given bitmap.
|
||||
|
||||
@return bitmap range iterator */
|
||||
xb_page_bitmap_range*
|
||||
xb_page_bitmap_range_init(
|
||||
/*======================*/
|
||||
xb_page_bitmap* bitmap, /*!< in: bitmap to iterate over */
|
||||
ulint space_id); /*!< in: space id */
|
||||
|
||||
/****************************************************************//**
|
||||
Get the next page id that has its bit set or cleared, i.e. equal to
|
||||
bit_value.
|
||||
|
||||
@return page id */
|
||||
ulint
|
||||
xb_page_bitmap_range_get_next_bit(
|
||||
/*==============================*/
|
||||
xb_page_bitmap_range* bitmap_range, /*!< in/out: bitmap range */
|
||||
ibool bit_value); /*!< in: bit value */
|
||||
|
||||
/****************************************************************//**
|
||||
Free the bitmap range iterator. */
|
||||
void
|
||||
xb_page_bitmap_range_deinit(
|
||||
/*========================*/
|
||||
xb_page_bitmap_range* bitmap_range); /*! in/out: bitmap range */
|
||||
|
||||
#endif
|
174
extra/mariabackup/common.h
Normal file
174
extra/mariabackup/common.h
Normal file
|
@ -0,0 +1,174 @@
|
|||
/******************************************************
|
||||
Copyright (c) 2011-2013 Percona LLC and/or its affiliates.
|
||||
|
||||
Common declarations for XtraBackup.
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; version 2 of the License.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
|
||||
|
||||
*******************************************************/
|
||||
|
||||
#ifndef XB_COMMON_H
|
||||
#define XB_COMMON_H
|
||||
|
||||
#include <my_global.h>
|
||||
#include <mysql_version.h>
|
||||
#include <fcntl.h>
|
||||
#include <stdarg.h>
|
||||
|
||||
|
||||
# define fil_is_user_tablespace_id(i) ((i) > srv_undo_tablespaces_open)
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#define stat _stati64
|
||||
#define PATH_MAX MAX_PATH
|
||||
#endif
|
||||
|
||||
#ifndef HAVE_VASPRINTF
|
||||
static inline int vasprintf(char **strp, const char *fmt, va_list args)
|
||||
{
|
||||
int len;
|
||||
#ifdef _MSC_VER
|
||||
len = _vscprintf(fmt, args);
|
||||
#else
|
||||
len = vsnprintf(NULL, 0, fmt, args);
|
||||
#endif
|
||||
if (len < 0)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
*strp = (char *)malloc(len + 1);
|
||||
if (!*strp)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
vsprintf(*strp, fmt, args);
|
||||
return len;
|
||||
}
|
||||
|
||||
static inline int asprintf(char **strp, const char *fmt,...)
|
||||
{
|
||||
va_list args;
|
||||
va_start(args, fmt);
|
||||
int len = vasprintf(strp, fmt, args);
|
||||
va_end(args);
|
||||
return len;
|
||||
}
|
||||
#endif
|
||||
|
||||
#define xb_a(expr) \
|
||||
do { \
|
||||
if (!(expr)) { \
|
||||
msg("Assertion \"%s\" failed at %s:%lu\n", \
|
||||
#expr, __FILE__, (ulong) __LINE__); \
|
||||
abort(); \
|
||||
} \
|
||||
} while (0);
|
||||
|
||||
#ifdef XB_DEBUG
|
||||
#define xb_ad(expr) xb_a(expr)
|
||||
#else
|
||||
#define xb_ad(expr)
|
||||
#endif
|
||||
|
||||
#define XB_DELTA_INFO_SUFFIX ".meta"
|
||||
|
||||
static inline int msg(const char *fmt, ...) ATTRIBUTE_FORMAT(printf, 1, 2);
|
||||
static inline int msg(const char *fmt, ...)
|
||||
{
|
||||
int result;
|
||||
va_list args;
|
||||
|
||||
va_start(args, fmt);
|
||||
result = vfprintf(stderr, fmt, args);
|
||||
va_end(args);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
static inline int msg_ts(const char *fmt, ...) ATTRIBUTE_FORMAT(printf, 1, 2);
|
||||
static inline int msg_ts(const char *fmt, ...)
|
||||
{
|
||||
int result;
|
||||
time_t t = time(NULL);
|
||||
char date[100];
|
||||
char *line;
|
||||
va_list args;
|
||||
|
||||
strftime(date, sizeof(date), "%y%m%d %H:%M:%S", localtime(&t));
|
||||
|
||||
va_start(args, fmt);
|
||||
result = vasprintf(&line, fmt, args);
|
||||
va_end(args);
|
||||
|
||||
if (result != -1) {
|
||||
result = fprintf(stderr, "%s %s", date, line);
|
||||
free(line);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/* Use POSIX_FADV_NORMAL when available */
|
||||
|
||||
#ifdef POSIX_FADV_NORMAL
|
||||
# define USE_POSIX_FADVISE
|
||||
#else
|
||||
# define POSIX_FADV_NORMAL
|
||||
# define POSIX_FADV_SEQUENTIAL
|
||||
# define POSIX_FADV_DONTNEED
|
||||
# define posix_fadvise(a,b,c,d) do {} while(0)
|
||||
#endif
|
||||
|
||||
/***********************************************************************
|
||||
Computes bit shift for a given value. If the argument is not a power
|
||||
of 2, returns 0.*/
|
||||
static inline size_t
|
||||
get_bit_shift(size_t value)
|
||||
{
|
||||
size_t shift;
|
||||
|
||||
if (value == 0)
|
||||
return 0;
|
||||
|
||||
for (shift = 0; !(value & 1); shift++) {
|
||||
value >>= 1;
|
||||
}
|
||||
return (value >> 1) ? 0 : shift;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
Read 'len' bytes from 'fd'. It is identical to my_read(..., MYF(MY_FULL_IO)),
|
||||
i.e. tries to combine partial reads into a single block of size 'len', except
|
||||
that it bails out on EOF or error, and returns the number of successfully read
|
||||
bytes instead. */
|
||||
static inline size_t
|
||||
xb_read_full(File fd, uchar *buf, size_t len)
|
||||
{
|
||||
size_t tlen = 0;
|
||||
size_t tbytes;
|
||||
|
||||
while (tlen < len) {
|
||||
tbytes = my_read(fd, buf, len - tlen, MYF(MY_WME));
|
||||
if (tbytes == 0 || tbytes == MY_FILE_ERROR) {
|
||||
break;
|
||||
}
|
||||
|
||||
buf += tbytes;
|
||||
tlen += tbytes;
|
||||
}
|
||||
|
||||
return tlen;
|
||||
}
|
||||
|
||||
#endif
|
33
extra/mariabackup/crc/CMakeLists.txt
Normal file
33
extra/mariabackup/crc/CMakeLists.txt
Normal file
|
@ -0,0 +1,33 @@
|
|||
# Copyright (c) 2017 Percona LLC and/or its affiliates.
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation; version 2 of the License.
|
||||
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program; if not, write to the Free Software
|
||||
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
|
||||
|
||||
PROJECT(crc C)
|
||||
|
||||
IF(NOT CMAKE_CROSSCOMPILING AND NOT MSVC)
|
||||
STRING(TOLOWER ${CMAKE_SYSTEM_PROCESSOR} processor)
|
||||
IF(processor MATCHES "86" OR processor MATCHES "amd64" OR processor MATCHES "x64")
|
||||
# Check for PCLMUL instruction
|
||||
CHECK_C_SOURCE_RUNS("
|
||||
int main()
|
||||
{
|
||||
asm volatile (\"pclmulqdq \\$0x00, %%xmm1, %%xmm0\":::\"cc\");
|
||||
return 0;
|
||||
}" HAVE_CLMUL_INSTRUCTION)
|
||||
ENDIF()
|
||||
ENDIF()
|
||||
IF(HAVE_CLMUL_INSTRUCTION)
|
||||
ADD_DEFINITIONS(-DHAVE_CLMUL_INSTRUCTION)
|
||||
ENDIF()
|
||||
ADD_LIBRARY(crc crc_glue.c crc-intel-pclmul.c)
|
21
extra/mariabackup/crc/config.h.cmake
Normal file
21
extra/mariabackup/crc/config.h.cmake
Normal file
|
@ -0,0 +1,21 @@
|
|||
/******************************************************
|
||||
Copyright (c) 2017 Percona LLC and/or its affiliates.
|
||||
|
||||
Zlib compatible CRC-32 implementation.
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; version 2 of the License.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
|
||||
|
||||
*******************************************************/
|
||||
|
||||
#cmakedefine HAVE_CLMUL_INSTRUCTION 1
|
511
extra/mariabackup/crc/crc-intel-pclmul.c
Normal file
511
extra/mariabackup/crc/crc-intel-pclmul.c
Normal file
|
@ -0,0 +1,511 @@
|
|||
/******************************************************
|
||||
Copyright (c) 2017 Percona LLC and/or its affiliates.
|
||||
|
||||
CRC32 using Intel's PCLMUL instruction.
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; version 2 of the License.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
|
||||
|
||||
*******************************************************/
|
||||
|
||||
/* crc-intel-pclmul.c - Intel PCLMUL accelerated CRC implementation
|
||||
* Copyright (C) 2016 Jussi Kivilinna <jussi.kivilinna@iki.fi>
|
||||
*
|
||||
* This file is part of Libgcrypt.
|
||||
*
|
||||
* Libgcrypt is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License as
|
||||
* published by the Free Software Foundation; either version 2.1 of
|
||||
* the License, or (at your option) any later version.
|
||||
*
|
||||
* Libgcrypt is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <stdint.h>
|
||||
|
||||
# define U64_C(c) (c ## UL)
|
||||
|
||||
typedef uint32_t u32;
|
||||
typedef uint16_t u16;
|
||||
typedef uint64_t u64;
|
||||
#ifndef byte
|
||||
typedef uint8_t byte;
|
||||
#endif
|
||||
|
||||
# define _gcry_bswap32 __builtin_bswap32
|
||||
|
||||
#if __GNUC__ >= 4 && defined(__x86_64__) && defined(HAVE_CLMUL_INSTRUCTION)
|
||||
|
||||
#if _GCRY_GCC_VERSION >= 40400 /* 4.4 */
|
||||
/* Prevent compiler from issuing SSE instructions between asm blocks. */
|
||||
# pragma GCC target("no-sse")
|
||||
#endif
|
||||
|
||||
|
||||
#define ALIGNED_16 __attribute__ ((aligned (16)))
|
||||
|
||||
|
||||
struct u16_unaligned_s
|
||||
{
|
||||
u16 a;
|
||||
} __attribute__((packed, aligned (1), may_alias));
|
||||
|
||||
|
||||
/* Constants structure for generic reflected/non-reflected CRC32 CLMUL
|
||||
* functions. */
|
||||
struct crc32_consts_s
|
||||
{
|
||||
/* k: { x^(32*17), x^(32*15), x^(32*5), x^(32*3), x^(32*2), 0 } mod P(x) */
|
||||
u64 k[6];
|
||||
/* my_p: { floor(x^64 / P(x)), P(x) } */
|
||||
u64 my_p[2];
|
||||
};
|
||||
|
||||
|
||||
/* CLMUL constants for CRC32 and CRC32RFC1510. */
|
||||
static const struct crc32_consts_s crc32_consts ALIGNED_16 =
|
||||
{
|
||||
{ /* k[6] = reverse_33bits( x^(32*y) mod P(x) ) */
|
||||
U64_C(0x154442bd4), U64_C(0x1c6e41596), /* y = { 17, 15 } */
|
||||
U64_C(0x1751997d0), U64_C(0x0ccaa009e), /* y = { 5, 3 } */
|
||||
U64_C(0x163cd6124), 0 /* y = 2 */
|
||||
},
|
||||
{ /* my_p[2] = reverse_33bits ( { floor(x^64 / P(x)), P(x) } ) */
|
||||
U64_C(0x1f7011641), U64_C(0x1db710641)
|
||||
}
|
||||
};
|
||||
|
||||
/* Common constants for CRC32 algorithms. */
|
||||
static const byte crc32_refl_shuf_shift[3 * 16] ALIGNED_16 =
|
||||
{
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
|
||||
0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
};
|
||||
static const byte crc32_partial_fold_input_mask[16 + 16] ALIGNED_16 =
|
||||
{
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
};
|
||||
static const u64 crc32_merge9to15_shuf[15 - 9 + 1][2] ALIGNED_16 =
|
||||
{
|
||||
{ U64_C(0x0706050403020100), U64_C(0xffffffffffffff0f) }, /* 9 */
|
||||
{ U64_C(0x0706050403020100), U64_C(0xffffffffffff0f0e) },
|
||||
{ U64_C(0x0706050403020100), U64_C(0xffffffffff0f0e0d) },
|
||||
{ U64_C(0x0706050403020100), U64_C(0xffffffff0f0e0d0c) },
|
||||
{ U64_C(0x0706050403020100), U64_C(0xffffff0f0e0d0c0b) },
|
||||
{ U64_C(0x0706050403020100), U64_C(0xffff0f0e0d0c0b0a) },
|
||||
{ U64_C(0x0706050403020100), U64_C(0xff0f0e0d0c0b0a09) }, /* 15 */
|
||||
};
|
||||
static const u64 crc32_merge5to7_shuf[7 - 5 + 1][2] ALIGNED_16 =
|
||||
{
|
||||
{ U64_C(0xffffff0703020100), U64_C(0xffffffffffffffff) }, /* 5 */
|
||||
{ U64_C(0xffff070603020100), U64_C(0xffffffffffffffff) },
|
||||
{ U64_C(0xff07060503020100), U64_C(0xffffffffffffffff) }, /* 7 */
|
||||
};
|
||||
|
||||
/* PCLMUL functions for reflected CRC32. */
|
||||
static inline void
|
||||
crc32_reflected_bulk (u32 *pcrc, const byte *inbuf, size_t inlen,
|
||||
const struct crc32_consts_s *consts)
|
||||
{
|
||||
if (inlen >= 8 * 16)
|
||||
{
|
||||
asm volatile ("movd %[crc], %%xmm4\n\t"
|
||||
"movdqu %[inbuf_0], %%xmm0\n\t"
|
||||
"movdqu %[inbuf_1], %%xmm1\n\t"
|
||||
"movdqu %[inbuf_2], %%xmm2\n\t"
|
||||
"movdqu %[inbuf_3], %%xmm3\n\t"
|
||||
"pxor %%xmm4, %%xmm0\n\t"
|
||||
:
|
||||
: [inbuf_0] "m" (inbuf[0 * 16]),
|
||||
[inbuf_1] "m" (inbuf[1 * 16]),
|
||||
[inbuf_2] "m" (inbuf[2 * 16]),
|
||||
[inbuf_3] "m" (inbuf[3 * 16]),
|
||||
[crc] "m" (*pcrc)
|
||||
);
|
||||
|
||||
inbuf += 4 * 16;
|
||||
inlen -= 4 * 16;
|
||||
|
||||
asm volatile ("movdqa %[k1k2], %%xmm4\n\t"
|
||||
:
|
||||
: [k1k2] "m" (consts->k[1 - 1])
|
||||
);
|
||||
|
||||
/* Fold by 4. */
|
||||
while (inlen >= 4 * 16)
|
||||
{
|
||||
asm volatile ("movdqu %[inbuf_0], %%xmm5\n\t"
|
||||
"movdqa %%xmm0, %%xmm6\n\t"
|
||||
"pclmulqdq $0x00, %%xmm4, %%xmm0\n\t"
|
||||
"pclmulqdq $0x11, %%xmm4, %%xmm6\n\t"
|
||||
"pxor %%xmm5, %%xmm0\n\t"
|
||||
"pxor %%xmm6, %%xmm0\n\t"
|
||||
|
||||
"movdqu %[inbuf_1], %%xmm5\n\t"
|
||||
"movdqa %%xmm1, %%xmm6\n\t"
|
||||
"pclmulqdq $0x00, %%xmm4, %%xmm1\n\t"
|
||||
"pclmulqdq $0x11, %%xmm4, %%xmm6\n\t"
|
||||
"pxor %%xmm5, %%xmm1\n\t"
|
||||
"pxor %%xmm6, %%xmm1\n\t"
|
||||
|
||||
"movdqu %[inbuf_2], %%xmm5\n\t"
|
||||
"movdqa %%xmm2, %%xmm6\n\t"
|
||||
"pclmulqdq $0x00, %%xmm4, %%xmm2\n\t"
|
||||
"pclmulqdq $0x11, %%xmm4, %%xmm6\n\t"
|
||||
"pxor %%xmm5, %%xmm2\n\t"
|
||||
"pxor %%xmm6, %%xmm2\n\t"
|
||||
|
||||
"movdqu %[inbuf_3], %%xmm5\n\t"
|
||||
"movdqa %%xmm3, %%xmm6\n\t"
|
||||
"pclmulqdq $0x00, %%xmm4, %%xmm3\n\t"
|
||||
"pclmulqdq $0x11, %%xmm4, %%xmm6\n\t"
|
||||
"pxor %%xmm5, %%xmm3\n\t"
|
||||
"pxor %%xmm6, %%xmm3\n\t"
|
||||
:
|
||||
: [inbuf_0] "m" (inbuf[0 * 16]),
|
||||
[inbuf_1] "m" (inbuf[1 * 16]),
|
||||
[inbuf_2] "m" (inbuf[2 * 16]),
|
||||
[inbuf_3] "m" (inbuf[3 * 16])
|
||||
);
|
||||
|
||||
inbuf += 4 * 16;
|
||||
inlen -= 4 * 16;
|
||||
}
|
||||
|
||||
asm volatile ("movdqa %[k3k4], %%xmm6\n\t"
|
||||
"movdqa %[my_p], %%xmm5\n\t"
|
||||
:
|
||||
: [k3k4] "m" (consts->k[3 - 1]),
|
||||
[my_p] "m" (consts->my_p[0])
|
||||
);
|
||||
|
||||
/* Fold 4 to 1. */
|
||||
|
||||
asm volatile ("movdqa %%xmm0, %%xmm4\n\t"
|
||||
"pclmulqdq $0x00, %%xmm6, %%xmm0\n\t"
|
||||
"pclmulqdq $0x11, %%xmm6, %%xmm4\n\t"
|
||||
"pxor %%xmm1, %%xmm0\n\t"
|
||||
"pxor %%xmm4, %%xmm0\n\t"
|
||||
|
||||
"movdqa %%xmm0, %%xmm4\n\t"
|
||||
"pclmulqdq $0x00, %%xmm6, %%xmm0\n\t"
|
||||
"pclmulqdq $0x11, %%xmm6, %%xmm4\n\t"
|
||||
"pxor %%xmm2, %%xmm0\n\t"
|
||||
"pxor %%xmm4, %%xmm0\n\t"
|
||||
|
||||
"movdqa %%xmm0, %%xmm4\n\t"
|
||||
"pclmulqdq $0x00, %%xmm6, %%xmm0\n\t"
|
||||
"pclmulqdq $0x11, %%xmm6, %%xmm4\n\t"
|
||||
"pxor %%xmm3, %%xmm0\n\t"
|
||||
"pxor %%xmm4, %%xmm0\n\t"
|
||||
:
|
||||
:
|
||||
);
|
||||
}
|
||||
else
|
||||
{
|
||||
asm volatile ("movd %[crc], %%xmm1\n\t"
|
||||
"movdqu %[inbuf], %%xmm0\n\t"
|
||||
"movdqa %[k3k4], %%xmm6\n\t"
|
||||
"pxor %%xmm1, %%xmm0\n\t"
|
||||
"movdqa %[my_p], %%xmm5\n\t"
|
||||
:
|
||||
: [inbuf] "m" (*inbuf),
|
||||
[crc] "m" (*pcrc),
|
||||
[k3k4] "m" (consts->k[3 - 1]),
|
||||
[my_p] "m" (consts->my_p[0])
|
||||
);
|
||||
|
||||
inbuf += 16;
|
||||
inlen -= 16;
|
||||
}
|
||||
|
||||
/* Fold by 1. */
|
||||
if (inlen >= 16)
|
||||
{
|
||||
while (inlen >= 16)
|
||||
{
|
||||
/* Load next block to XMM2. Fold XMM0 to XMM0:XMM1. */
|
||||
asm volatile ("movdqu %[inbuf], %%xmm2\n\t"
|
||||
"movdqa %%xmm0, %%xmm1\n\t"
|
||||
"pclmulqdq $0x00, %%xmm6, %%xmm0\n\t"
|
||||
"pclmulqdq $0x11, %%xmm6, %%xmm1\n\t"
|
||||
"pxor %%xmm2, %%xmm0\n\t"
|
||||
"pxor %%xmm1, %%xmm0\n\t"
|
||||
:
|
||||
: [inbuf] "m" (*inbuf)
|
||||
);
|
||||
|
||||
inbuf += 16;
|
||||
inlen -= 16;
|
||||
}
|
||||
}
|
||||
|
||||
/* Partial fold. */
|
||||
if (inlen)
|
||||
{
|
||||
/* Load last input and add padding zeros. */
|
||||
asm volatile ("movdqu %[shr_shuf], %%xmm3\n\t"
|
||||
"movdqu %[shl_shuf], %%xmm4\n\t"
|
||||
"movdqu %[mask], %%xmm2\n\t"
|
||||
|
||||
"movdqa %%xmm0, %%xmm1\n\t"
|
||||
"pshufb %%xmm4, %%xmm0\n\t"
|
||||
"movdqu %[inbuf], %%xmm4\n\t"
|
||||
"pshufb %%xmm3, %%xmm1\n\t"
|
||||
"pand %%xmm4, %%xmm2\n\t"
|
||||
"por %%xmm1, %%xmm2\n\t"
|
||||
|
||||
"movdqa %%xmm0, %%xmm1\n\t"
|
||||
"pclmulqdq $0x00, %%xmm6, %%xmm0\n\t"
|
||||
"pclmulqdq $0x11, %%xmm6, %%xmm1\n\t"
|
||||
"pxor %%xmm2, %%xmm0\n\t"
|
||||
"pxor %%xmm1, %%xmm0\n\t"
|
||||
:
|
||||
: [inbuf] "m" (*(inbuf - 16 + inlen)),
|
||||
[mask] "m" (crc32_partial_fold_input_mask[inlen]),
|
||||
[shl_shuf] "m" (crc32_refl_shuf_shift[inlen]),
|
||||
[shr_shuf] "m" (crc32_refl_shuf_shift[inlen + 16])
|
||||
);
|
||||
|
||||
inbuf += inlen;
|
||||
inlen -= inlen;
|
||||
}
|
||||
|
||||
/* Final fold. */
|
||||
asm volatile (/* reduce 128-bits to 96-bits */
|
||||
"movdqa %%xmm0, %%xmm1\n\t"
|
||||
"pclmulqdq $0x10, %%xmm6, %%xmm0\n\t"
|
||||
"psrldq $8, %%xmm1\n\t"
|
||||
"pxor %%xmm1, %%xmm0\n\t"
|
||||
|
||||
/* reduce 96-bits to 64-bits */
|
||||
"pshufd $0xfc, %%xmm0, %%xmm1\n\t" /* [00][00][00][x] */
|
||||
"pshufd $0xf9, %%xmm0, %%xmm0\n\t" /* [00][00][x>>64][x>>32] */
|
||||
"pclmulqdq $0x00, %[k5], %%xmm1\n\t" /* [00][00][xx][xx] */
|
||||
"pxor %%xmm1, %%xmm0\n\t" /* top 64-bit are zero */
|
||||
|
||||
/* barrett reduction */
|
||||
"pshufd $0xf3, %%xmm0, %%xmm1\n\t" /* [00][00][x>>32][00] */
|
||||
"pslldq $4, %%xmm0\n\t" /* [??][x>>32][??][??] */
|
||||
"pclmulqdq $0x00, %%xmm5, %%xmm1\n\t" /* [00][xx][xx][00] */
|
||||
"pclmulqdq $0x10, %%xmm5, %%xmm1\n\t" /* [00][xx][xx][00] */
|
||||
"pxor %%xmm1, %%xmm0\n\t"
|
||||
|
||||
/* store CRC */
|
||||
"pextrd $2, %%xmm0, %[out]\n\t"
|
||||
: [out] "=m" (*pcrc)
|
||||
: [k5] "m" (consts->k[5 - 1])
|
||||
);
|
||||
}
|
||||
|
||||
static inline void
|
||||
crc32_reflected_less_than_16 (u32 *pcrc, const byte *inbuf, size_t inlen,
|
||||
const struct crc32_consts_s *consts)
|
||||
{
|
||||
if (inlen < 4)
|
||||
{
|
||||
u32 crc = *pcrc;
|
||||
u32 data;
|
||||
|
||||
asm volatile ("movdqa %[my_p], %%xmm5\n\t"
|
||||
:
|
||||
: [my_p] "m" (consts->my_p[0])
|
||||
);
|
||||
|
||||
if (inlen == 1)
|
||||
{
|
||||
data = inbuf[0];
|
||||
data ^= crc;
|
||||
data <<= 24;
|
||||
crc >>= 8;
|
||||
}
|
||||
else if (inlen == 2)
|
||||
{
|
||||
data = ((const struct u16_unaligned_s *)inbuf)->a;
|
||||
data ^= crc;
|
||||
data <<= 16;
|
||||
crc >>= 16;
|
||||
}
|
||||
else
|
||||
{
|
||||
data = ((const struct u16_unaligned_s *)inbuf)->a;
|
||||
data |= inbuf[2] << 16;
|
||||
data ^= crc;
|
||||
data <<= 8;
|
||||
crc >>= 24;
|
||||
}
|
||||
|
||||
/* Barrett reduction */
|
||||
asm volatile ("movd %[in], %%xmm0\n\t"
|
||||
"movd %[crc], %%xmm1\n\t"
|
||||
|
||||
"pclmulqdq $0x00, %%xmm5, %%xmm0\n\t" /* [00][00][xx][xx] */
|
||||
"psllq $32, %%xmm1\n\t"
|
||||
"pshufd $0xfc, %%xmm0, %%xmm0\n\t" /* [00][00][00][x] */
|
||||
"pclmulqdq $0x10, %%xmm5, %%xmm0\n\t" /* [00][00][xx][xx] */
|
||||
"pxor %%xmm1, %%xmm0\n\t"
|
||||
|
||||
"pextrd $1, %%xmm0, %[out]\n\t"
|
||||
: [out] "=m" (*pcrc)
|
||||
: [in] "rm" (data),
|
||||
[crc] "rm" (crc)
|
||||
);
|
||||
}
|
||||
else if (inlen == 4)
|
||||
{
|
||||
/* Barrett reduction */
|
||||
asm volatile ("movd %[crc], %%xmm1\n\t"
|
||||
"movd %[in], %%xmm0\n\t"
|
||||
"movdqa %[my_p], %%xmm5\n\t"
|
||||
"pxor %%xmm1, %%xmm0\n\t"
|
||||
|
||||
"pclmulqdq $0x00, %%xmm5, %%xmm0\n\t" /* [00][00][xx][xx] */
|
||||
"pshufd $0xfc, %%xmm0, %%xmm0\n\t" /* [00][00][00][x] */
|
||||
"pclmulqdq $0x10, %%xmm5, %%xmm0\n\t" /* [00][00][xx][xx] */
|
||||
|
||||
"pextrd $1, %%xmm0, %[out]\n\t"
|
||||
: [out] "=m" (*pcrc)
|
||||
: [in] "m" (*inbuf),
|
||||
[crc] "m" (*pcrc),
|
||||
[my_p] "m" (consts->my_p[0])
|
||||
);
|
||||
}
|
||||
else
|
||||
{
|
||||
asm volatile ("movdqu %[shuf], %%xmm4\n\t"
|
||||
"movd %[crc], %%xmm1\n\t"
|
||||
"movdqa %[my_p], %%xmm5\n\t"
|
||||
"movdqa %[k3k4], %%xmm6\n\t"
|
||||
:
|
||||
: [shuf] "m" (crc32_refl_shuf_shift[inlen]),
|
||||
[crc] "m" (*pcrc),
|
||||
[my_p] "m" (consts->my_p[0]),
|
||||
[k3k4] "m" (consts->k[3 - 1])
|
||||
);
|
||||
|
||||
if (inlen >= 8)
|
||||
{
|
||||
asm volatile ("movq %[inbuf], %%xmm0\n\t"
|
||||
:
|
||||
: [inbuf] "m" (*inbuf)
|
||||
);
|
||||
if (inlen > 8)
|
||||
{
|
||||
asm volatile (/*"pinsrq $1, %[inbuf_tail], %%xmm0\n\t"*/
|
||||
"movq %[inbuf_tail], %%xmm2\n\t"
|
||||
"punpcklqdq %%xmm2, %%xmm0\n\t"
|
||||
"pshufb %[merge_shuf], %%xmm0\n\t"
|
||||
:
|
||||
: [inbuf_tail] "m" (inbuf[inlen - 8]),
|
||||
[merge_shuf] "m"
|
||||
(*crc32_merge9to15_shuf[inlen - 9])
|
||||
);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
asm volatile ("movd %[inbuf], %%xmm0\n\t"
|
||||
"pinsrd $1, %[inbuf_tail], %%xmm0\n\t"
|
||||
"pshufb %[merge_shuf], %%xmm0\n\t"
|
||||
:
|
||||
: [inbuf] "m" (*inbuf),
|
||||
[inbuf_tail] "m" (inbuf[inlen - 4]),
|
||||
[merge_shuf] "m"
|
||||
(*crc32_merge5to7_shuf[inlen - 5])
|
||||
);
|
||||
}
|
||||
|
||||
/* Final fold. */
|
||||
asm volatile ("pxor %%xmm1, %%xmm0\n\t"
|
||||
"pshufb %%xmm4, %%xmm0\n\t"
|
||||
|
||||
/* reduce 128-bits to 96-bits */
|
||||
"movdqa %%xmm0, %%xmm1\n\t"
|
||||
"pclmulqdq $0x10, %%xmm6, %%xmm0\n\t"
|
||||
"psrldq $8, %%xmm1\n\t"
|
||||
"pxor %%xmm1, %%xmm0\n\t" /* top 32-bit are zero */
|
||||
|
||||
/* reduce 96-bits to 64-bits */
|
||||
"pshufd $0xfc, %%xmm0, %%xmm1\n\t" /* [00][00][00][x] */
|
||||
"pshufd $0xf9, %%xmm0, %%xmm0\n\t" /* [00][00][x>>64][x>>32] */
|
||||
"pclmulqdq $0x00, %[k5], %%xmm1\n\t" /* [00][00][xx][xx] */
|
||||
"pxor %%xmm1, %%xmm0\n\t" /* top 64-bit are zero */
|
||||
|
||||
/* barrett reduction */
|
||||
"pshufd $0xf3, %%xmm0, %%xmm1\n\t" /* [00][00][x>>32][00] */
|
||||
"pslldq $4, %%xmm0\n\t" /* [??][x>>32][??][??] */
|
||||
"pclmulqdq $0x00, %%xmm5, %%xmm1\n\t" /* [00][xx][xx][00] */
|
||||
"pclmulqdq $0x10, %%xmm5, %%xmm1\n\t" /* [00][xx][xx][00] */
|
||||
"pxor %%xmm1, %%xmm0\n\t"
|
||||
|
||||
/* store CRC */
|
||||
"pextrd $2, %%xmm0, %[out]\n\t"
|
||||
: [out] "=m" (*pcrc)
|
||||
: [k5] "m" (consts->k[5 - 1])
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
crc32_intel_pclmul (u32 *pcrc, const byte *inbuf, size_t inlen)
|
||||
{
|
||||
const struct crc32_consts_s *consts = &crc32_consts;
|
||||
#if defined(__x86_64__) && defined(__WIN64__)
|
||||
char win64tmp[2 * 16];
|
||||
|
||||
/* XMM6-XMM7 need to be restored after use. */
|
||||
asm volatile ("movdqu %%xmm6, 0*16(%0)\n\t"
|
||||
"movdqu %%xmm7, 1*16(%0)\n\t"
|
||||
:
|
||||
: "r" (win64tmp)
|
||||
: "memory");
|
||||
#endif
|
||||
|
||||
if (!inlen)
|
||||
return;
|
||||
|
||||
if (inlen >= 16)
|
||||
crc32_reflected_bulk(pcrc, inbuf, inlen, consts);
|
||||
else
|
||||
crc32_reflected_less_than_16(pcrc, inbuf, inlen, consts);
|
||||
|
||||
#if defined(__x86_64__) && defined(__WIN64__)
|
||||
/* Restore used registers. */
|
||||
asm volatile("movdqu 0*16(%0), %%xmm6\n\t"
|
||||
"movdqu 1*16(%0), %%xmm7\n\t"
|
||||
:
|
||||
: "r" (win64tmp)
|
||||
: "memory");
|
||||
#endif
|
||||
}
|
||||
|
||||
#endif
|
25
extra/mariabackup/crc/crc-intel-pclmul.h
Normal file
25
extra/mariabackup/crc/crc-intel-pclmul.h
Normal file
|
@ -0,0 +1,25 @@
|
|||
/******************************************************
|
||||
Copyright (c) 2017 Percona LLC and/or its affiliates.
|
||||
|
||||
CRC32 using Intel's PCLMUL instruction.
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; version 2 of the License.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
|
||||
|
||||
*******************************************************/
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stddef.h>
|
||||
|
||||
void
|
||||
crc32_intel_pclmul(uint32_t *pcrc, const uint8_t *inbuf, size_t inlen);
|
72
extra/mariabackup/crc/crc_glue.c
Normal file
72
extra/mariabackup/crc/crc_glue.c
Normal file
|
@ -0,0 +1,72 @@
|
|||
/******************************************************
|
||||
Copyright (c) 2017 Percona LLC and/or its affiliates.
|
||||
|
||||
Zlib compatible CRC-32 implementation.
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; version 2 of the License.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
|
||||
|
||||
*******************************************************/
|
||||
|
||||
#include "crc_glue.h"
|
||||
#include "crc-intel-pclmul.h"
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
#include <zlib.h>
|
||||
|
||||
#if __GNUC__ >= 4 && defined(__x86_64__)
|
||||
static int pclmul_enabled = 0;
|
||||
#endif
|
||||
|
||||
#if defined(__GNUC__) && defined(__x86_64__)
|
||||
static
|
||||
uint32_t
|
||||
cpuid(uint32_t* ecx, uint32_t* edx)
|
||||
{
|
||||
uint32_t level;
|
||||
|
||||
asm("cpuid" : "=a" (level) : "a" (0) : "ebx", "ecx", "edx");
|
||||
|
||||
if (level < 1) {
|
||||
return level;
|
||||
}
|
||||
|
||||
asm("cpuid" : "=c" (*ecx), "=d" (*edx)
|
||||
: "a" (1)
|
||||
: "ebx");
|
||||
|
||||
return level;
|
||||
}
|
||||
#endif
|
||||
|
||||
void crc_init() {
|
||||
#if defined(__GNUC__) && defined(__x86_64__)
|
||||
uint32_t ecx, edx;
|
||||
|
||||
if (cpuid(&ecx, &edx) > 0) {
|
||||
pclmul_enabled = ((ecx >> 19) & 1) && ((ecx >> 1) & 1);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
unsigned long crc32_iso3309(unsigned long crc, const unsigned char *buf, unsigned int len)
|
||||
{
|
||||
#if __GNUC__ >= 4 && defined(__x86_64__) && defined(HAVE_CLMUL_INSTRUCTION)
|
||||
if (pclmul_enabled) {
|
||||
uint32_t crc_accum = crc ^ 0xffffffffL;
|
||||
crc32_intel_pclmul(&crc_accum, buf, len);
|
||||
return crc_accum ^ 0xffffffffL;
|
||||
}
|
||||
#endif
|
||||
return crc32(crc, buf, len);
|
||||
}
|
31
extra/mariabackup/crc/crc_glue.h
Normal file
31
extra/mariabackup/crc/crc_glue.h
Normal file
|
@ -0,0 +1,31 @@
|
|||
/******************************************************
|
||||
Copyright (c) 2017 Percona LLC and/or its affiliates.
|
||||
|
||||
Zlib compatible CRC-32 implementation.
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; version 2 of the License.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
|
||||
|
||||
*******************************************************/
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
void crc_init();
|
||||
unsigned long crc32_iso3309(unsigned long crc, const unsigned char *buf, unsigned int len);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
137
extra/mariabackup/datasink.c
Normal file
137
extra/mariabackup/datasink.c
Normal file
|
@ -0,0 +1,137 @@
|
|||
/******************************************************
|
||||
Copyright (c) 2011-2013 Percona LLC and/or its affiliates.
|
||||
|
||||
Data sink interface.
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; version 2 of the License.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
|
||||
|
||||
*******************************************************/
|
||||
|
||||
#include <my_base.h>
|
||||
#include "common.h"
|
||||
#include "datasink.h"
|
||||
#include "ds_compress.h"
|
||||
#include "ds_archive.h"
|
||||
#include "ds_xbstream.h"
|
||||
#include "ds_local.h"
|
||||
#include "ds_stdout.h"
|
||||
#include "ds_tmpfile.h"
|
||||
#include "ds_buffer.h"
|
||||
|
||||
/************************************************************************
|
||||
Create a datasink of the specified type */
|
||||
ds_ctxt_t *
|
||||
ds_create(const char *root, ds_type_t type)
|
||||
{
|
||||
datasink_t *ds;
|
||||
ds_ctxt_t *ctxt;
|
||||
|
||||
switch (type) {
|
||||
case DS_TYPE_STDOUT:
|
||||
ds = &datasink_stdout;
|
||||
break;
|
||||
case DS_TYPE_LOCAL:
|
||||
ds = &datasink_local;
|
||||
break;
|
||||
case DS_TYPE_ARCHIVE:
|
||||
#ifdef HAVE_LIBARCHIVE
|
||||
ds = &datasink_archive;
|
||||
#else
|
||||
msg("Error : mariabackup was built without libarchive support");
|
||||
exit(EXIT_FAILURE);
|
||||
#endif
|
||||
break;
|
||||
case DS_TYPE_XBSTREAM:
|
||||
ds = &datasink_xbstream;
|
||||
break;
|
||||
case DS_TYPE_COMPRESS:
|
||||
ds = &datasink_compress;
|
||||
break;
|
||||
case DS_TYPE_ENCRYPT:
|
||||
case DS_TYPE_DECRYPT:
|
||||
msg("Error : mariabackup does not support encrypted backups.");
|
||||
exit(EXIT_FAILURE);
|
||||
break;
|
||||
|
||||
case DS_TYPE_TMPFILE:
|
||||
ds = &datasink_tmpfile;
|
||||
break;
|
||||
case DS_TYPE_BUFFER:
|
||||
ds = &datasink_buffer;
|
||||
break;
|
||||
default:
|
||||
msg("Unknown datasink type: %d\n", type);
|
||||
xb_ad(0);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
ctxt = ds->init(root);
|
||||
if (ctxt != NULL) {
|
||||
ctxt->datasink = ds;
|
||||
} else {
|
||||
msg("Error: failed to initialize datasink.\n");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
return ctxt;
|
||||
}
|
||||
|
||||
/************************************************************************
|
||||
Open a datasink file */
|
||||
ds_file_t *
|
||||
ds_open(ds_ctxt_t *ctxt, const char *path, MY_STAT *stat)
|
||||
{
|
||||
ds_file_t *file;
|
||||
|
||||
file = ctxt->datasink->open(ctxt, path, stat);
|
||||
if (file != NULL) {
|
||||
file->datasink = ctxt->datasink;
|
||||
}
|
||||
|
||||
return file;
|
||||
}
|
||||
|
||||
/************************************************************************
|
||||
Write to a datasink file.
|
||||
@return 0 on success, 1 on error. */
|
||||
int
|
||||
ds_write(ds_file_t *file, const void *buf, size_t len)
|
||||
{
|
||||
return file->datasink->write(file, buf, len);
|
||||
}
|
||||
|
||||
/************************************************************************
|
||||
Close a datasink file.
|
||||
@return 0 on success, 1, on error. */
|
||||
int
|
||||
ds_close(ds_file_t *file)
|
||||
{
|
||||
return file->datasink->close(file);
|
||||
}
|
||||
|
||||
/************************************************************************
|
||||
Destroy a datasink handle */
|
||||
void
|
||||
ds_destroy(ds_ctxt_t *ctxt)
|
||||
{
|
||||
ctxt->datasink->deinit(ctxt);
|
||||
}
|
||||
|
||||
/************************************************************************
|
||||
Set the destination pipe for a datasink (only makes sense for compress and
|
||||
tmpfile). */
|
||||
void ds_set_pipe(ds_ctxt_t *ctxt, ds_ctxt_t *pipe_ctxt)
|
||||
{
|
||||
ctxt->pipe_ctxt = pipe_ctxt;
|
||||
}
|
100
extra/mariabackup/datasink.h
Normal file
100
extra/mariabackup/datasink.h
Normal file
|
@ -0,0 +1,100 @@
|
|||
/******************************************************
|
||||
Copyright (c) 2011-2013 Percona LLC and/or its affiliates.
|
||||
|
||||
Data sink interface.
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; version 2 of the License.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
|
||||
|
||||
*******************************************************/
|
||||
|
||||
#ifndef XB_DATASINK_H
|
||||
#define XB_DATASINK_H
|
||||
|
||||
#include <my_global.h>
|
||||
#include <my_dir.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
extern char *xtrabackup_tmpdir;
|
||||
struct datasink_struct;
|
||||
typedef struct datasink_struct datasink_t;
|
||||
|
||||
typedef struct ds_ctxt {
|
||||
datasink_t *datasink;
|
||||
char *root;
|
||||
void *ptr;
|
||||
struct ds_ctxt *pipe_ctxt;
|
||||
} ds_ctxt_t;
|
||||
|
||||
typedef struct {
|
||||
void *ptr;
|
||||
char *path;
|
||||
datasink_t *datasink;
|
||||
} ds_file_t;
|
||||
|
||||
struct datasink_struct {
|
||||
ds_ctxt_t *(*init)(const char *root);
|
||||
ds_file_t *(*open)(ds_ctxt_t *ctxt, const char *path, MY_STAT *stat);
|
||||
int (*write)(ds_file_t *file, const void *buf, size_t len);
|
||||
int (*close)(ds_file_t *file);
|
||||
void (*deinit)(ds_ctxt_t *ctxt);
|
||||
};
|
||||
|
||||
/* Supported datasink types */
|
||||
typedef enum {
|
||||
DS_TYPE_STDOUT,
|
||||
DS_TYPE_LOCAL,
|
||||
DS_TYPE_ARCHIVE,
|
||||
DS_TYPE_XBSTREAM,
|
||||
DS_TYPE_COMPRESS,
|
||||
DS_TYPE_ENCRYPT,
|
||||
DS_TYPE_DECRYPT,
|
||||
DS_TYPE_TMPFILE,
|
||||
DS_TYPE_BUFFER
|
||||
} ds_type_t;
|
||||
|
||||
/************************************************************************
|
||||
Create a datasink of the specified type */
|
||||
ds_ctxt_t *ds_create(const char *root, ds_type_t type);
|
||||
|
||||
/************************************************************************
|
||||
Open a datasink file */
|
||||
ds_file_t *ds_open(ds_ctxt_t *ctxt, const char *path, MY_STAT *stat);
|
||||
|
||||
/************************************************************************
|
||||
Write to a datasink file.
|
||||
@return 0 on success, 1 on error. */
|
||||
int ds_write(ds_file_t *file, const void *buf, size_t len);
|
||||
|
||||
/************************************************************************
|
||||
Close a datasink file.
|
||||
@return 0 on success, 1, on error. */
|
||||
int ds_close(ds_file_t *file);
|
||||
|
||||
/************************************************************************
|
||||
Destroy a datasink handle */
|
||||
void ds_destroy(ds_ctxt_t *ctxt);
|
||||
|
||||
/************************************************************************
|
||||
Set the destination pipe for a datasink (only makes sense for compress and
|
||||
tmpfile). */
|
||||
void ds_set_pipe(ds_ctxt_t *ctxt, ds_ctxt_t *pipe_ctxt);
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /* extern "C" */
|
||||
#endif
|
||||
|
||||
#endif /* XB_DATASINK_H */
|
280
extra/mariabackup/ds_archive.c
Normal file
280
extra/mariabackup/ds_archive.c
Normal file
|
@ -0,0 +1,280 @@
|
|||
/******************************************************
|
||||
Copyright (c) 2013 Percona LLC and/or its affiliates.
|
||||
|
||||
Streaming implementation for XtraBackup.
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; version 2 of the License.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
|
||||
|
||||
*******************************************************/
|
||||
|
||||
#include <my_base.h>
|
||||
#include <archive.h>
|
||||
#include <archive_entry.h>
|
||||
#include "common.h"
|
||||
#include "datasink.h"
|
||||
|
||||
#if ARCHIVE_VERSION_NUMBER < 3000000
|
||||
#define archive_write_add_filter_none(X) archive_write_set_compression_none(X)
|
||||
#define archive_write_free(X) archive_write_finish(X)
|
||||
#endif
|
||||
|
||||
typedef struct {
|
||||
struct archive *archive;
|
||||
ds_file_t *dest_file;
|
||||
pthread_mutex_t mutex;
|
||||
} ds_archive_ctxt_t;
|
||||
|
||||
typedef struct {
|
||||
struct archive_entry *entry;
|
||||
ds_archive_ctxt_t *archive_ctxt;
|
||||
} ds_archive_file_t;
|
||||
|
||||
|
||||
/***********************************************************************
|
||||
General archive interface */
|
||||
|
||||
static ds_ctxt_t *archive_init(const char *root);
|
||||
static ds_file_t *archive_open(ds_ctxt_t *ctxt, const char *path,
|
||||
MY_STAT *mystat);
|
||||
static int archive_write(ds_file_t *file, const void *buf, size_t len);
|
||||
static int archive_close(ds_file_t *file);
|
||||
static void archive_deinit(ds_ctxt_t *ctxt);
|
||||
|
||||
datasink_t datasink_archive = {
|
||||
&archive_init,
|
||||
&archive_open,
|
||||
&archive_write,
|
||||
&archive_close,
|
||||
&archive_deinit
|
||||
};
|
||||
|
||||
static
|
||||
int
|
||||
my_archive_open_callback(struct archive *a __attribute__((unused)),
|
||||
void *data __attribute__((unused)))
|
||||
{
|
||||
return ARCHIVE_OK;
|
||||
}
|
||||
|
||||
static
|
||||
ssize_t
|
||||
my_archive_write_callback(struct archive *a __attribute__((unused)),
|
||||
void *data, const void *buffer, size_t length)
|
||||
{
|
||||
ds_archive_ctxt_t *archive_ctxt;
|
||||
|
||||
archive_ctxt = (ds_archive_ctxt_t *) data;
|
||||
|
||||
xb_ad(archive_ctxt != NULL);
|
||||
xb_ad(archive_ctxt->dest_file != NULL);
|
||||
|
||||
if (!ds_write(archive_ctxt->dest_file, buffer, length)) {
|
||||
return length;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
static
|
||||
int
|
||||
my_archive_close_callback(struct archive *a __attribute__((unused)),
|
||||
void *data __attribute__((unused)))
|
||||
{
|
||||
return ARCHIVE_OK;
|
||||
}
|
||||
|
||||
static
|
||||
ds_ctxt_t *
|
||||
archive_init(const char *root __attribute__((unused)))
|
||||
{
|
||||
ds_ctxt_t *ctxt;
|
||||
ds_archive_ctxt_t *archive_ctxt;
|
||||
struct archive *a;
|
||||
|
||||
ctxt = my_malloc(sizeof(ds_ctxt_t) + sizeof(ds_archive_ctxt_t),
|
||||
MYF(MY_FAE));
|
||||
archive_ctxt = (ds_archive_ctxt_t *)(ctxt + 1);
|
||||
|
||||
if (pthread_mutex_init(&archive_ctxt->mutex, NULL)) {
|
||||
msg("archive_init: pthread_mutex_init() failed.\n");
|
||||
goto err;
|
||||
}
|
||||
|
||||
a = archive_write_new();
|
||||
if (a == NULL) {
|
||||
msg("archive_write_new() failed.\n");
|
||||
goto err;
|
||||
}
|
||||
|
||||
archive_ctxt->archive = a;
|
||||
archive_ctxt->dest_file = NULL;
|
||||
|
||||
if(archive_write_add_filter_none(a) != ARCHIVE_OK ||
|
||||
archive_write_set_format_pax_restricted(a) != ARCHIVE_OK ||
|
||||
/* disable internal buffering so we don't have to flush the
|
||||
output in xtrabackup */
|
||||
archive_write_set_bytes_per_block(a, 0) != ARCHIVE_OK) {
|
||||
msg("failed to set libarchive archive options: %s\n",
|
||||
archive_error_string(a));
|
||||
archive_write_free(a);
|
||||
goto err;
|
||||
}
|
||||
|
||||
if (archive_write_open(a, archive_ctxt, my_archive_open_callback,
|
||||
my_archive_write_callback,
|
||||
my_archive_close_callback) != ARCHIVE_OK) {
|
||||
msg("cannot open output archive.\n");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
ctxt->ptr = archive_ctxt;
|
||||
|
||||
return ctxt;
|
||||
|
||||
err:
|
||||
my_free(ctxt);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static
|
||||
ds_file_t *
|
||||
archive_open(ds_ctxt_t *ctxt, const char *path, MY_STAT *mystat)
|
||||
{
|
||||
ds_archive_ctxt_t *archive_ctxt;
|
||||
ds_ctxt_t *dest_ctxt;
|
||||
ds_file_t *file;
|
||||
ds_archive_file_t *archive_file;
|
||||
|
||||
struct archive *a;
|
||||
struct archive_entry *entry;
|
||||
|
||||
xb_ad(ctxt->pipe_ctxt != NULL);
|
||||
dest_ctxt = ctxt->pipe_ctxt;
|
||||
|
||||
archive_ctxt = (ds_archive_ctxt_t *) ctxt->ptr;
|
||||
|
||||
pthread_mutex_lock(&archive_ctxt->mutex);
|
||||
if (archive_ctxt->dest_file == NULL) {
|
||||
archive_ctxt->dest_file = ds_open(dest_ctxt, path, mystat);
|
||||
if (archive_ctxt->dest_file == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
pthread_mutex_unlock(&archive_ctxt->mutex);
|
||||
|
||||
file = (ds_file_t *) my_malloc(sizeof(ds_file_t) +
|
||||
sizeof(ds_archive_file_t),
|
||||
MYF(MY_FAE));
|
||||
|
||||
archive_file = (ds_archive_file_t *) (file + 1);
|
||||
|
||||
a = archive_ctxt->archive;
|
||||
|
||||
entry = archive_entry_new();
|
||||
if (entry == NULL) {
|
||||
msg("archive_entry_new() failed.\n");
|
||||
goto err;
|
||||
}
|
||||
|
||||
archive_entry_set_size(entry, mystat->st_size);
|
||||
archive_entry_set_mode(entry, 0660);
|
||||
archive_entry_set_filetype(entry, AE_IFREG);
|
||||
archive_entry_set_pathname(entry, path);
|
||||
archive_entry_set_mtime(entry, mystat->st_mtime, 0);
|
||||
|
||||
archive_file->entry = entry;
|
||||
archive_file->archive_ctxt = archive_ctxt;
|
||||
|
||||
if (archive_write_header(a, entry) != ARCHIVE_OK) {
|
||||
msg("archive_write_header() failed.\n");
|
||||
archive_entry_free(entry);
|
||||
goto err;
|
||||
}
|
||||
|
||||
file->ptr = archive_file;
|
||||
file->path = archive_ctxt->dest_file->path;
|
||||
|
||||
return file;
|
||||
|
||||
err:
|
||||
if (archive_ctxt->dest_file) {
|
||||
ds_close(archive_ctxt->dest_file);
|
||||
archive_ctxt->dest_file = NULL;
|
||||
}
|
||||
my_free(file);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static
|
||||
int
|
||||
archive_write(ds_file_t *file, const void *buf, size_t len)
|
||||
{
|
||||
ds_archive_file_t *archive_file;
|
||||
struct archive *a;
|
||||
|
||||
archive_file = (ds_archive_file_t *) file->ptr;
|
||||
|
||||
a = archive_file->archive_ctxt->archive;
|
||||
|
||||
xb_ad(archive_file->archive_ctxt->dest_file != NULL);
|
||||
if (archive_write_data(a, buf, len) < 0) {
|
||||
msg("archive_write_data() failed: %s (errno = %d)\n",
|
||||
archive_error_string(a), archive_errno(a));
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static
|
||||
int
|
||||
archive_close(ds_file_t *file)
|
||||
{
|
||||
ds_archive_file_t *archive_file;
|
||||
int rc = 0;
|
||||
|
||||
archive_file = (ds_archive_file_t *)file->ptr;
|
||||
|
||||
archive_entry_free(archive_file->entry);
|
||||
|
||||
my_free(file);
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
static
|
||||
void
|
||||
archive_deinit(ds_ctxt_t *ctxt)
|
||||
{
|
||||
struct archive *a;
|
||||
ds_archive_ctxt_t *archive_ctxt;
|
||||
|
||||
archive_ctxt = (ds_archive_ctxt_t *) ctxt->ptr;
|
||||
|
||||
a = archive_ctxt->archive;
|
||||
|
||||
if (archive_write_close(a) != ARCHIVE_OK) {
|
||||
msg("archive_write_close() failed.\n");
|
||||
}
|
||||
archive_write_free(a);
|
||||
|
||||
if (archive_ctxt->dest_file) {
|
||||
ds_close(archive_ctxt->dest_file);
|
||||
archive_ctxt->dest_file = NULL;
|
||||
}
|
||||
|
||||
pthread_mutex_destroy(&archive_ctxt->mutex);
|
||||
|
||||
my_free(ctxt);
|
||||
}
|
28
extra/mariabackup/ds_archive.h
Normal file
28
extra/mariabackup/ds_archive.h
Normal file
|
@ -0,0 +1,28 @@
|
|||
/******************************************************
|
||||
Copyright (c) 2013 Percona LLC and/or its affiliates.
|
||||
|
||||
Streaming interface for XtraBackup.
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; version 2 of the License.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
|
||||
|
||||
*******************************************************/
|
||||
|
||||
#ifndef DS_ARCHIVE_H
|
||||
#define DS_ARCHIVE_H
|
||||
|
||||
#include "datasink.h"
|
||||
|
||||
extern datasink_t datasink_archive;
|
||||
|
||||
#endif
|
189
extra/mariabackup/ds_buffer.c
Normal file
189
extra/mariabackup/ds_buffer.c
Normal file
|
@ -0,0 +1,189 @@
|
|||
/******************************************************
|
||||
Copyright (c) 2012-2013 Percona LLC and/or its affiliates.
|
||||
|
||||
buffer datasink for XtraBackup.
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; version 2 of the License.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
|
||||
|
||||
*******************************************************/
|
||||
|
||||
/* Does buffered output to a destination datasink set with ds_set_pipe().
|
||||
Writes to the destination datasink are guaranteed to not be smaller than a
|
||||
specified buffer size (DS_DEFAULT_BUFFER_SIZE by default), with the only
|
||||
exception for the last write for a file. */
|
||||
|
||||
#include <mysql_version.h>
|
||||
#include <my_base.h>
|
||||
#include "ds_buffer.h"
|
||||
#include "common.h"
|
||||
#include "datasink.h"
|
||||
|
||||
#define DS_DEFAULT_BUFFER_SIZE (64 * 1024)
|
||||
|
||||
typedef struct {
|
||||
ds_file_t *dst_file;
|
||||
char *buf;
|
||||
size_t pos;
|
||||
size_t size;
|
||||
} ds_buffer_file_t;
|
||||
|
||||
typedef struct {
|
||||
size_t buffer_size;
|
||||
} ds_buffer_ctxt_t;
|
||||
|
||||
static ds_ctxt_t *buffer_init(const char *root);
|
||||
static ds_file_t *buffer_open(ds_ctxt_t *ctxt, const char *path,
|
||||
MY_STAT *mystat);
|
||||
static int buffer_write(ds_file_t *file, const void *buf, size_t len);
|
||||
static int buffer_close(ds_file_t *file);
|
||||
static void buffer_deinit(ds_ctxt_t *ctxt);
|
||||
|
||||
datasink_t datasink_buffer = {
|
||||
&buffer_init,
|
||||
&buffer_open,
|
||||
&buffer_write,
|
||||
&buffer_close,
|
||||
&buffer_deinit
|
||||
};
|
||||
|
||||
/* Change the default buffer size */
|
||||
void ds_buffer_set_size(ds_ctxt_t *ctxt, size_t size)
|
||||
{
|
||||
ds_buffer_ctxt_t *buffer_ctxt = (ds_buffer_ctxt_t *) ctxt->ptr;
|
||||
|
||||
buffer_ctxt->buffer_size = size;
|
||||
}
|
||||
|
||||
static ds_ctxt_t *
|
||||
buffer_init(const char *root)
|
||||
{
|
||||
ds_ctxt_t *ctxt;
|
||||
ds_buffer_ctxt_t *buffer_ctxt;
|
||||
|
||||
ctxt = my_malloc(sizeof(ds_ctxt_t) + sizeof(ds_buffer_ctxt_t),
|
||||
MYF(MY_FAE));
|
||||
buffer_ctxt = (ds_buffer_ctxt_t *) (ctxt + 1);
|
||||
buffer_ctxt->buffer_size = DS_DEFAULT_BUFFER_SIZE;
|
||||
|
||||
ctxt->ptr = buffer_ctxt;
|
||||
ctxt->root = my_strdup(root, MYF(MY_FAE));
|
||||
|
||||
return ctxt;
|
||||
}
|
||||
|
||||
static ds_file_t *
|
||||
buffer_open(ds_ctxt_t *ctxt, const char *path, MY_STAT *mystat)
|
||||
{
|
||||
ds_buffer_ctxt_t *buffer_ctxt;
|
||||
ds_ctxt_t *pipe_ctxt;
|
||||
ds_file_t *dst_file;
|
||||
ds_file_t *file;
|
||||
ds_buffer_file_t *buffer_file;
|
||||
|
||||
pipe_ctxt = ctxt->pipe_ctxt;
|
||||
xb_a(pipe_ctxt != NULL);
|
||||
|
||||
dst_file = ds_open(pipe_ctxt, path, mystat);
|
||||
if (dst_file == NULL) {
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
buffer_ctxt = (ds_buffer_ctxt_t *) ctxt->ptr;
|
||||
|
||||
file = (ds_file_t *) my_malloc(sizeof(ds_file_t) +
|
||||
sizeof(ds_buffer_file_t) +
|
||||
buffer_ctxt->buffer_size,
|
||||
MYF(MY_FAE));
|
||||
|
||||
buffer_file = (ds_buffer_file_t *) (file + 1);
|
||||
buffer_file->dst_file = dst_file;
|
||||
buffer_file->buf = (char *) (buffer_file + 1);
|
||||
buffer_file->size = buffer_ctxt->buffer_size;
|
||||
buffer_file->pos = 0;
|
||||
|
||||
file->path = dst_file->path;
|
||||
file->ptr = buffer_file;
|
||||
|
||||
return file;
|
||||
}
|
||||
|
||||
static int
|
||||
buffer_write(ds_file_t *file, const void *buf, size_t len)
|
||||
{
|
||||
ds_buffer_file_t *buffer_file;
|
||||
|
||||
buffer_file = (ds_buffer_file_t *) file->ptr;
|
||||
|
||||
while (len > 0) {
|
||||
if (buffer_file->pos + len > buffer_file->size) {
|
||||
if (buffer_file->pos > 0) {
|
||||
size_t bytes;
|
||||
|
||||
bytes = buffer_file->size - buffer_file->pos;
|
||||
memcpy(buffer_file->buf + buffer_file->pos, buf,
|
||||
bytes);
|
||||
|
||||
if (ds_write(buffer_file->dst_file,
|
||||
buffer_file->buf,
|
||||
buffer_file->size)) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
buffer_file->pos = 0;
|
||||
|
||||
buf = (const char *) buf + bytes;
|
||||
len -= bytes;
|
||||
} else {
|
||||
/* We don't have any buffered bytes, just write
|
||||
the entire source buffer */
|
||||
if (ds_write(buffer_file->dst_file, buf, len)) {
|
||||
return 1;
|
||||
}
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
memcpy(buffer_file->buf + buffer_file->pos, buf, len);
|
||||
buffer_file->pos += len;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
buffer_close(ds_file_t *file)
|
||||
{
|
||||
ds_buffer_file_t *buffer_file;
|
||||
int ret;
|
||||
|
||||
buffer_file = (ds_buffer_file_t *) file->ptr;
|
||||
if (buffer_file->pos > 0) {
|
||||
ds_write(buffer_file->dst_file, buffer_file->buf,
|
||||
buffer_file->pos);
|
||||
}
|
||||
|
||||
ret = ds_close(buffer_file->dst_file);
|
||||
|
||||
my_free(file);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void
|
||||
buffer_deinit(ds_ctxt_t *ctxt)
|
||||
{
|
||||
my_free(ctxt->root);
|
||||
my_free(ctxt);
|
||||
}
|
39
extra/mariabackup/ds_buffer.h
Normal file
39
extra/mariabackup/ds_buffer.h
Normal file
|
@ -0,0 +1,39 @@
|
|||
/******************************************************
|
||||
Copyright (c) 2012-2013 Percona LLC and/or its affiliates.
|
||||
|
||||
buffer datasink for XtraBackup.
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; version 2 of the License.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
|
||||
|
||||
*******************************************************/
|
||||
|
||||
#ifndef DS_BUFFER_H
|
||||
#define DS_BUFFER_H
|
||||
|
||||
#include "datasink.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
extern datasink_t datasink_buffer;
|
||||
|
||||
/* Change the default buffer size */
|
||||
void ds_buffer_set_size(ds_ctxt_t *ctxt, size_t size);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
462
extra/mariabackup/ds_compress.c
Normal file
462
extra/mariabackup/ds_compress.c
Normal file
|
@ -0,0 +1,462 @@
|
|||
/******************************************************
|
||||
Copyright (c) 2011-2013 Percona LLC and/or its affiliates.
|
||||
|
||||
Compressing datasink implementation for XtraBackup.
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; version 2 of the License.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
|
||||
|
||||
*******************************************************/
|
||||
|
||||
#include <mysql_version.h>
|
||||
#include <my_base.h>
|
||||
#include <quicklz.h>
|
||||
#include <zlib.h>
|
||||
#include "common.h"
|
||||
#include "datasink.h"
|
||||
|
||||
#define COMPRESS_CHUNK_SIZE ((size_t) (xtrabackup_compress_chunk_size))
|
||||
#define MY_QLZ_COMPRESS_OVERHEAD 400
|
||||
|
||||
typedef struct {
|
||||
pthread_t id;
|
||||
uint num;
|
||||
pthread_mutex_t ctrl_mutex;
|
||||
pthread_cond_t ctrl_cond;
|
||||
pthread_mutex_t data_mutex;
|
||||
pthread_cond_t data_cond;
|
||||
my_bool started;
|
||||
my_bool data_avail;
|
||||
my_bool cancelled;
|
||||
const char *from;
|
||||
size_t from_len;
|
||||
char *to;
|
||||
size_t to_len;
|
||||
qlz_state_compress state;
|
||||
ulong adler;
|
||||
} comp_thread_ctxt_t;
|
||||
|
||||
typedef struct {
|
||||
comp_thread_ctxt_t *threads;
|
||||
uint nthreads;
|
||||
} ds_compress_ctxt_t;
|
||||
|
||||
typedef struct {
|
||||
ds_file_t *dest_file;
|
||||
ds_compress_ctxt_t *comp_ctxt;
|
||||
size_t bytes_processed;
|
||||
} ds_compress_file_t;
|
||||
|
||||
/* Compression options */
|
||||
extern char *xtrabackup_compress_alg;
|
||||
extern uint xtrabackup_compress_threads;
|
||||
extern ulonglong xtrabackup_compress_chunk_size;
|
||||
|
||||
static ds_ctxt_t *compress_init(const char *root);
|
||||
static ds_file_t *compress_open(ds_ctxt_t *ctxt, const char *path,
|
||||
MY_STAT *mystat);
|
||||
static int compress_write(ds_file_t *file, const void *buf, size_t len);
|
||||
static int compress_close(ds_file_t *file);
|
||||
static void compress_deinit(ds_ctxt_t *ctxt);
|
||||
|
||||
datasink_t datasink_compress = {
|
||||
&compress_init,
|
||||
&compress_open,
|
||||
&compress_write,
|
||||
&compress_close,
|
||||
&compress_deinit
|
||||
};
|
||||
|
||||
static inline int write_uint32_le(ds_file_t *file, ulong n);
|
||||
static inline int write_uint64_le(ds_file_t *file, ulonglong n);
|
||||
|
||||
static comp_thread_ctxt_t *create_worker_threads(uint n);
|
||||
static void destroy_worker_threads(comp_thread_ctxt_t *threads, uint n);
|
||||
static void *compress_worker_thread_func(void *arg);
|
||||
|
||||
static
|
||||
ds_ctxt_t *
|
||||
compress_init(const char *root)
|
||||
{
|
||||
ds_ctxt_t *ctxt;
|
||||
ds_compress_ctxt_t *compress_ctxt;
|
||||
comp_thread_ctxt_t *threads;
|
||||
|
||||
/* Create and initialize the worker threads */
|
||||
threads = create_worker_threads(xtrabackup_compress_threads);
|
||||
if (threads == NULL) {
|
||||
msg("compress: failed to create worker threads.\n");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
ctxt = (ds_ctxt_t *) my_malloc(sizeof(ds_ctxt_t) +
|
||||
sizeof(ds_compress_ctxt_t),
|
||||
MYF(MY_FAE));
|
||||
|
||||
compress_ctxt = (ds_compress_ctxt_t *) (ctxt + 1);
|
||||
compress_ctxt->threads = threads;
|
||||
compress_ctxt->nthreads = xtrabackup_compress_threads;
|
||||
|
||||
ctxt->ptr = compress_ctxt;
|
||||
ctxt->root = my_strdup(root, MYF(MY_FAE));
|
||||
|
||||
return ctxt;
|
||||
}
|
||||
|
||||
static
|
||||
ds_file_t *
|
||||
compress_open(ds_ctxt_t *ctxt, const char *path, MY_STAT *mystat)
|
||||
{
|
||||
ds_compress_ctxt_t *comp_ctxt;
|
||||
ds_ctxt_t *dest_ctxt;
|
||||
ds_file_t *dest_file;
|
||||
char new_name[FN_REFLEN];
|
||||
size_t name_len;
|
||||
ds_file_t *file;
|
||||
ds_compress_file_t *comp_file;
|
||||
|
||||
xb_ad(ctxt->pipe_ctxt != NULL);
|
||||
dest_ctxt = ctxt->pipe_ctxt;
|
||||
|
||||
comp_ctxt = (ds_compress_ctxt_t *) ctxt->ptr;
|
||||
|
||||
/* Append the .qp extension to the filename */
|
||||
fn_format(new_name, path, "", ".qp", MYF(MY_APPEND_EXT));
|
||||
|
||||
dest_file = ds_open(dest_ctxt, new_name, mystat);
|
||||
if (dest_file == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* Write the qpress archive header */
|
||||
if (ds_write(dest_file, "qpress10", 8) ||
|
||||
write_uint64_le(dest_file, COMPRESS_CHUNK_SIZE)) {
|
||||
goto err;
|
||||
}
|
||||
|
||||
/* We are going to create a one-file "flat" (i.e. with no
|
||||
subdirectories) archive. So strip the directory part from the path and
|
||||
remove the '.qp' suffix. */
|
||||
fn_format(new_name, path, "", "", MYF(MY_REPLACE_DIR));
|
||||
|
||||
/* Write the qpress file header */
|
||||
name_len = strlen(new_name);
|
||||
if (ds_write(dest_file, "F", 1) ||
|
||||
write_uint32_le(dest_file, (uint)name_len) ||
|
||||
/* we want to write the terminating \0 as well */
|
||||
ds_write(dest_file, new_name, name_len + 1)) {
|
||||
goto err;
|
||||
}
|
||||
|
||||
file = (ds_file_t *) my_malloc(sizeof(ds_file_t) +
|
||||
sizeof(ds_compress_file_t),
|
||||
MYF(MY_FAE));
|
||||
comp_file = (ds_compress_file_t *) (file + 1);
|
||||
comp_file->dest_file = dest_file;
|
||||
comp_file->comp_ctxt = comp_ctxt;
|
||||
comp_file->bytes_processed = 0;
|
||||
|
||||
file->ptr = comp_file;
|
||||
file->path = dest_file->path;
|
||||
|
||||
return file;
|
||||
|
||||
err:
|
||||
ds_close(dest_file);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static
|
||||
int
|
||||
compress_write(ds_file_t *file, const void *buf, size_t len)
|
||||
{
|
||||
ds_compress_file_t *comp_file;
|
||||
ds_compress_ctxt_t *comp_ctxt;
|
||||
comp_thread_ctxt_t *threads;
|
||||
comp_thread_ctxt_t *thd;
|
||||
uint nthreads;
|
||||
uint i;
|
||||
const char *ptr;
|
||||
ds_file_t *dest_file;
|
||||
|
||||
comp_file = (ds_compress_file_t *) file->ptr;
|
||||
comp_ctxt = comp_file->comp_ctxt;
|
||||
dest_file = comp_file->dest_file;
|
||||
|
||||
threads = comp_ctxt->threads;
|
||||
nthreads = comp_ctxt->nthreads;
|
||||
|
||||
ptr = (const char *) buf;
|
||||
while (len > 0) {
|
||||
uint max_thread;
|
||||
|
||||
/* Send data to worker threads for compression */
|
||||
for (i = 0; i < nthreads; i++) {
|
||||
size_t chunk_len;
|
||||
|
||||
thd = threads + i;
|
||||
|
||||
pthread_mutex_lock(&thd->ctrl_mutex);
|
||||
|
||||
chunk_len = (len > COMPRESS_CHUNK_SIZE) ?
|
||||
COMPRESS_CHUNK_SIZE : len;
|
||||
thd->from = ptr;
|
||||
thd->from_len = chunk_len;
|
||||
|
||||
pthread_mutex_lock(&thd->data_mutex);
|
||||
thd->data_avail = TRUE;
|
||||
pthread_cond_signal(&thd->data_cond);
|
||||
pthread_mutex_unlock(&thd->data_mutex);
|
||||
|
||||
len -= chunk_len;
|
||||
if (len == 0) {
|
||||
break;
|
||||
}
|
||||
ptr += chunk_len;
|
||||
}
|
||||
|
||||
max_thread = (i < nthreads) ? i : nthreads - 1;
|
||||
|
||||
/* Reap and stream the compressed data */
|
||||
for (i = 0; i <= max_thread; i++) {
|
||||
thd = threads + i;
|
||||
|
||||
pthread_mutex_lock(&thd->data_mutex);
|
||||
while (thd->data_avail == TRUE) {
|
||||
pthread_cond_wait(&thd->data_cond,
|
||||
&thd->data_mutex);
|
||||
}
|
||||
|
||||
xb_a(threads[i].to_len > 0);
|
||||
|
||||
if (ds_write(dest_file, "NEWBNEWB", 8) ||
|
||||
write_uint64_le(dest_file,
|
||||
comp_file->bytes_processed)) {
|
||||
msg("compress: write to the destination stream "
|
||||
"failed.\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
comp_file->bytes_processed += threads[i].from_len;
|
||||
|
||||
if (write_uint32_le(dest_file, threads[i].adler) ||
|
||||
ds_write(dest_file, threads[i].to,
|
||||
threads[i].to_len)) {
|
||||
msg("compress: write to the destination stream "
|
||||
"failed.\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
pthread_mutex_unlock(&threads[i].data_mutex);
|
||||
pthread_mutex_unlock(&threads[i].ctrl_mutex);
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static
|
||||
int
|
||||
compress_close(ds_file_t *file)
|
||||
{
|
||||
ds_compress_file_t *comp_file;
|
||||
ds_file_t *dest_file;
|
||||
int rc;
|
||||
|
||||
comp_file = (ds_compress_file_t *) file->ptr;
|
||||
dest_file = comp_file->dest_file;
|
||||
|
||||
/* Write the qpress file trailer */
|
||||
ds_write(dest_file, "ENDSENDS", 8);
|
||||
|
||||
/* Supposedly the number of written bytes should be written as a
|
||||
"recovery information" in the file trailer, but in reality qpress
|
||||
always writes 8 zeros here. Let's do the same */
|
||||
|
||||
write_uint64_le(dest_file, 0);
|
||||
|
||||
rc = ds_close(dest_file);
|
||||
|
||||
my_free(file);
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
static
|
||||
void
|
||||
compress_deinit(ds_ctxt_t *ctxt)
|
||||
{
|
||||
ds_compress_ctxt_t *comp_ctxt;
|
||||
|
||||
xb_ad(ctxt->pipe_ctxt != NULL);
|
||||
|
||||
comp_ctxt = (ds_compress_ctxt_t *) ctxt->ptr;;
|
||||
|
||||
destroy_worker_threads(comp_ctxt->threads, comp_ctxt->nthreads);
|
||||
|
||||
my_free(ctxt->root);
|
||||
my_free(ctxt);
|
||||
}
|
||||
|
||||
static inline
|
||||
int
|
||||
write_uint32_le(ds_file_t *file, ulong n)
|
||||
{
|
||||
char tmp[4];
|
||||
|
||||
int4store(tmp, n);
|
||||
return ds_write(file, tmp, sizeof(tmp));
|
||||
}
|
||||
|
||||
static inline
|
||||
int
|
||||
write_uint64_le(ds_file_t *file, ulonglong n)
|
||||
{
|
||||
char tmp[8];
|
||||
|
||||
int8store(tmp, n);
|
||||
return ds_write(file, tmp, sizeof(tmp));
|
||||
}
|
||||
|
||||
static
|
||||
comp_thread_ctxt_t *
|
||||
create_worker_threads(uint n)
|
||||
{
|
||||
comp_thread_ctxt_t *threads;
|
||||
uint i;
|
||||
|
||||
threads = (comp_thread_ctxt_t *)
|
||||
my_malloc(sizeof(comp_thread_ctxt_t) * n, MYF(MY_FAE));
|
||||
|
||||
for (i = 0; i < n; i++) {
|
||||
comp_thread_ctxt_t *thd = threads + i;
|
||||
|
||||
thd->num = i + 1;
|
||||
thd->started = FALSE;
|
||||
thd->cancelled = FALSE;
|
||||
thd->data_avail = FALSE;
|
||||
|
||||
thd->to = (char *) my_malloc(COMPRESS_CHUNK_SIZE +
|
||||
MY_QLZ_COMPRESS_OVERHEAD,
|
||||
MYF(MY_FAE));
|
||||
|
||||
/* Initialize the control mutex and condition var */
|
||||
if (pthread_mutex_init(&thd->ctrl_mutex, NULL) ||
|
||||
pthread_cond_init(&thd->ctrl_cond, NULL)) {
|
||||
goto err;
|
||||
}
|
||||
|
||||
/* Initialize and data mutex and condition var */
|
||||
if (pthread_mutex_init(&thd->data_mutex, NULL) ||
|
||||
pthread_cond_init(&thd->data_cond, NULL)) {
|
||||
goto err;
|
||||
}
|
||||
|
||||
pthread_mutex_lock(&thd->ctrl_mutex);
|
||||
|
||||
if (pthread_create(&thd->id, NULL, compress_worker_thread_func,
|
||||
thd)) {
|
||||
msg("compress: pthread_create() failed: "
|
||||
"errno = %d\n", errno);
|
||||
goto err;
|
||||
}
|
||||
}
|
||||
|
||||
/* Wait for the threads to start */
|
||||
for (i = 0; i < n; i++) {
|
||||
comp_thread_ctxt_t *thd = threads + i;
|
||||
|
||||
while (thd->started == FALSE)
|
||||
pthread_cond_wait(&thd->ctrl_cond, &thd->ctrl_mutex);
|
||||
pthread_mutex_unlock(&thd->ctrl_mutex);
|
||||
}
|
||||
|
||||
return threads;
|
||||
|
||||
err:
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static
|
||||
void
|
||||
destroy_worker_threads(comp_thread_ctxt_t *threads, uint n)
|
||||
{
|
||||
uint i;
|
||||
|
||||
for (i = 0; i < n; i++) {
|
||||
comp_thread_ctxt_t *thd = threads + i;
|
||||
|
||||
pthread_mutex_lock(&thd->data_mutex);
|
||||
threads[i].cancelled = TRUE;
|
||||
pthread_cond_signal(&thd->data_cond);
|
||||
pthread_mutex_unlock(&thd->data_mutex);
|
||||
|
||||
pthread_join(thd->id, NULL);
|
||||
|
||||
pthread_cond_destroy(&thd->data_cond);
|
||||
pthread_mutex_destroy(&thd->data_mutex);
|
||||
pthread_cond_destroy(&thd->ctrl_cond);
|
||||
pthread_mutex_destroy(&thd->ctrl_mutex);
|
||||
|
||||
my_free(thd->to);
|
||||
}
|
||||
|
||||
my_free(threads);
|
||||
}
|
||||
|
||||
static
|
||||
void *
|
||||
compress_worker_thread_func(void *arg)
|
||||
{
|
||||
comp_thread_ctxt_t *thd = (comp_thread_ctxt_t *) arg;
|
||||
|
||||
pthread_mutex_lock(&thd->ctrl_mutex);
|
||||
|
||||
pthread_mutex_lock(&thd->data_mutex);
|
||||
|
||||
thd->started = TRUE;
|
||||
pthread_cond_signal(&thd->ctrl_cond);
|
||||
|
||||
pthread_mutex_unlock(&thd->ctrl_mutex);
|
||||
|
||||
while (1) {
|
||||
thd->data_avail = FALSE;
|
||||
pthread_cond_signal(&thd->data_cond);
|
||||
|
||||
while (!thd->data_avail && !thd->cancelled) {
|
||||
pthread_cond_wait(&thd->data_cond, &thd->data_mutex);
|
||||
}
|
||||
|
||||
if (thd->cancelled)
|
||||
break;
|
||||
|
||||
thd->to_len = qlz_compress(thd->from, thd->to, thd->from_len,
|
||||
&thd->state);
|
||||
|
||||
/* qpress uses 0x00010000 as the initial value, but its own
|
||||
Adler-32 implementation treats the value differently:
|
||||
1. higher order bits are the sum of all bytes in the sequence
|
||||
2. lower order bits are the sum of resulting values at every
|
||||
step.
|
||||
So it's the other way around as compared to zlib's adler32().
|
||||
That's why 0x00000001 is being passed here to be compatible
|
||||
with qpress implementation. */
|
||||
|
||||
thd->adler = adler32(0x00000001, (uchar *) thd->to,
|
||||
(uInt)thd->to_len);
|
||||
}
|
||||
|
||||
pthread_mutex_unlock(&thd->data_mutex);
|
||||
|
||||
return NULL;
|
||||
}
|
28
extra/mariabackup/ds_compress.h
Normal file
28
extra/mariabackup/ds_compress.h
Normal file
|
@ -0,0 +1,28 @@
|
|||
/******************************************************
|
||||
Copyright (c) 2011-2013 Percona LLC and/or its affiliates.
|
||||
|
||||
Compression interface for XtraBackup.
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; version 2 of the License.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
|
||||
|
||||
*******************************************************/
|
||||
|
||||
#ifndef DS_COMPRESS_H
|
||||
#define DS_COMPRESS_H
|
||||
|
||||
#include "datasink.h"
|
||||
|
||||
extern datasink_t datasink_compress;
|
||||
|
||||
#endif
|
665
extra/mariabackup/ds_decrypt.c
Normal file
665
extra/mariabackup/ds_decrypt.c
Normal file
|
@ -0,0 +1,665 @@
|
|||
/******************************************************
|
||||
Copyright (c) 2017 Percona LLC and/or its affiliates.
|
||||
|
||||
Encryption datasink implementation for XtraBackup.
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; version 2 of the License.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
|
||||
|
||||
*******************************************************/
|
||||
|
||||
|
||||
#include <my_base.h>
|
||||
#include "common.h"
|
||||
#include "datasink.h"
|
||||
#include "xbcrypt.h"
|
||||
#include "xbcrypt_common.h"
|
||||
#include "crc_glue.h"
|
||||
|
||||
typedef struct {
|
||||
pthread_t id;
|
||||
uint num;
|
||||
pthread_mutex_t ctrl_mutex;
|
||||
pthread_cond_t ctrl_cond;
|
||||
pthread_mutex_t data_mutex;
|
||||
pthread_cond_t data_cond;
|
||||
my_bool started;
|
||||
my_bool data_avail;
|
||||
my_bool cancelled;
|
||||
my_bool failed;
|
||||
const uchar *from;
|
||||
size_t from_len;
|
||||
uchar *to;
|
||||
size_t to_len;
|
||||
size_t to_size;
|
||||
const uchar *iv;
|
||||
size_t iv_len;
|
||||
unsigned long long offset;
|
||||
my_bool hash_appended;
|
||||
gcry_cipher_hd_t cipher_handle;
|
||||
xb_rcrypt_result_t parse_result;
|
||||
} crypt_thread_ctxt_t;
|
||||
|
||||
typedef struct {
|
||||
crypt_thread_ctxt_t *threads;
|
||||
uint nthreads;
|
||||
int encrypt_algo;
|
||||
size_t chunk_size;
|
||||
char *encrypt_key;
|
||||
char *encrypt_key_file;
|
||||
} ds_decrypt_ctxt_t;
|
||||
|
||||
typedef struct {
|
||||
ds_decrypt_ctxt_t *crypt_ctxt;
|
||||
size_t bytes_processed;
|
||||
ds_file_t *dest_file;
|
||||
uchar *buf;
|
||||
size_t buf_len;
|
||||
size_t buf_size;
|
||||
} ds_decrypt_file_t;
|
||||
|
||||
int ds_decrypt_encrypt_threads = 1;
|
||||
|
||||
static ds_ctxt_t *decrypt_init(const char *root);
|
||||
static ds_file_t *decrypt_open(ds_ctxt_t *ctxt, const char *path,
|
||||
MY_STAT *mystat);
|
||||
static int decrypt_write(ds_file_t *file, const void *buf, size_t len);
|
||||
static int decrypt_close(ds_file_t *file);
|
||||
static void decrypt_deinit(ds_ctxt_t *ctxt);
|
||||
|
||||
datasink_t datasink_decrypt = {
|
||||
&decrypt_init,
|
||||
&decrypt_open,
|
||||
&decrypt_write,
|
||||
&decrypt_close,
|
||||
&decrypt_deinit
|
||||
};
|
||||
|
||||
static crypt_thread_ctxt_t *create_worker_threads(uint n);
|
||||
static void destroy_worker_threads(crypt_thread_ctxt_t *threads, uint n);
|
||||
static void *decrypt_worker_thread_func(void *arg);
|
||||
|
||||
static
|
||||
ds_ctxt_t *
|
||||
decrypt_init(const char *root)
|
||||
{
|
||||
ds_ctxt_t *ctxt;
|
||||
ds_decrypt_ctxt_t *decrypt_ctxt;
|
||||
crypt_thread_ctxt_t *threads;
|
||||
|
||||
if (xb_crypt_init(NULL)) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* Create and initialize the worker threads */
|
||||
threads = create_worker_threads(ds_decrypt_encrypt_threads);
|
||||
if (threads == NULL) {
|
||||
msg("decrypt: failed to create worker threads.\n");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
ctxt = (ds_ctxt_t *) my_malloc(sizeof(ds_ctxt_t) +
|
||||
sizeof(ds_decrypt_ctxt_t),
|
||||
MYF(MY_FAE));
|
||||
|
||||
decrypt_ctxt = (ds_decrypt_ctxt_t *) (ctxt + 1);
|
||||
decrypt_ctxt->threads = threads;
|
||||
decrypt_ctxt->nthreads = ds_decrypt_encrypt_threads;
|
||||
|
||||
ctxt->ptr = decrypt_ctxt;
|
||||
ctxt->root = my_strdup(root, MYF(MY_FAE));
|
||||
|
||||
return ctxt;
|
||||
}
|
||||
|
||||
static
|
||||
ds_file_t *
|
||||
decrypt_open(ds_ctxt_t *ctxt, const char *path, MY_STAT *mystat)
|
||||
{
|
||||
ds_ctxt_t *dest_ctxt;
|
||||
|
||||
ds_decrypt_ctxt_t *crypt_ctxt;
|
||||
ds_decrypt_file_t *crypt_file;
|
||||
|
||||
char new_name[FN_REFLEN];
|
||||
ds_file_t *file;
|
||||
|
||||
xb_ad(ctxt->pipe_ctxt != NULL);
|
||||
dest_ctxt = ctxt->pipe_ctxt;
|
||||
|
||||
crypt_ctxt = (ds_decrypt_ctxt_t *) ctxt->ptr;
|
||||
|
||||
|
||||
file = (ds_file_t *) my_malloc(sizeof(ds_file_t) +
|
||||
sizeof(ds_decrypt_file_t),
|
||||
MYF(MY_FAE|MY_ZEROFILL));
|
||||
|
||||
crypt_file = (ds_decrypt_file_t *) (file + 1);
|
||||
|
||||
/* Remove the .xbcrypt extension from the filename */
|
||||
strncpy(new_name, path, FN_REFLEN);
|
||||
new_name[strlen(new_name) - 8] = 0;
|
||||
crypt_file->dest_file = ds_open(dest_ctxt, new_name, mystat);
|
||||
if (crypt_file->dest_file == NULL) {
|
||||
msg("decrypt: ds_open(\"%s\") failed.\n", new_name);
|
||||
goto err;
|
||||
}
|
||||
|
||||
crypt_file->crypt_ctxt = crypt_ctxt;
|
||||
crypt_file->buf = NULL;
|
||||
crypt_file->buf_size = 0;
|
||||
crypt_file->buf_len = 0;
|
||||
|
||||
file->ptr = crypt_file;
|
||||
file->path = crypt_file->dest_file->path;
|
||||
|
||||
return file;
|
||||
|
||||
err:
|
||||
if (crypt_file->dest_file) {
|
||||
ds_close(crypt_file->dest_file);
|
||||
}
|
||||
my_free(file);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
#define CHECK_BUF_SIZE(ptr, size, buf, len) \
|
||||
if (ptr + size - buf > (ssize_t) len) { \
|
||||
result = XB_CRYPT_READ_INCOMPLETE; \
|
||||
goto exit; \
|
||||
}
|
||||
|
||||
static
|
||||
xb_rcrypt_result_t
|
||||
parse_xbcrypt_chunk(crypt_thread_ctxt_t *thd, const uchar *buf, size_t len,
|
||||
size_t *bytes_processed)
|
||||
{
|
||||
const uchar *ptr;
|
||||
uint version;
|
||||
ulong checksum, checksum_exp;
|
||||
ulonglong tmp;
|
||||
xb_rcrypt_result_t result = XB_CRYPT_READ_CHUNK;
|
||||
|
||||
*bytes_processed = 0;
|
||||
ptr = buf;
|
||||
|
||||
CHECK_BUF_SIZE(ptr, XB_CRYPT_CHUNK_MAGIC_SIZE, buf, len);
|
||||
if (memcmp(ptr, XB_CRYPT_CHUNK_MAGIC3,
|
||||
XB_CRYPT_CHUNK_MAGIC_SIZE) == 0) {
|
||||
version = 3;
|
||||
} else if (memcmp(ptr, XB_CRYPT_CHUNK_MAGIC2,
|
||||
XB_CRYPT_CHUNK_MAGIC_SIZE) == 0) {
|
||||
version = 2;
|
||||
} else if (memcmp(ptr, XB_CRYPT_CHUNK_MAGIC1,
|
||||
XB_CRYPT_CHUNK_MAGIC_SIZE) == 0) {
|
||||
version = 1;
|
||||
} else {
|
||||
msg("%s:%s: wrong chunk magic at offset 0x%llx.\n",
|
||||
my_progname, __FUNCTION__, thd->offset);
|
||||
result = XB_CRYPT_READ_ERROR;
|
||||
goto exit;
|
||||
}
|
||||
|
||||
ptr += XB_CRYPT_CHUNK_MAGIC_SIZE;
|
||||
thd->offset += XB_CRYPT_CHUNK_MAGIC_SIZE;
|
||||
|
||||
CHECK_BUF_SIZE(ptr, 8, buf, len);
|
||||
tmp = uint8korr(ptr); /* reserved */
|
||||
ptr += 8;
|
||||
thd->offset += 8;
|
||||
|
||||
CHECK_BUF_SIZE(ptr, 8, buf, len);
|
||||
tmp = uint8korr(ptr); /* original size */
|
||||
ptr += 8;
|
||||
if (tmp > INT_MAX) {
|
||||
msg("%s:%s: invalid original size at offset 0x%llx.\n",
|
||||
my_progname, __FUNCTION__, thd->offset);
|
||||
result = XB_CRYPT_READ_ERROR;
|
||||
goto exit;
|
||||
}
|
||||
thd->offset += 8;
|
||||
thd->to_len = (size_t)tmp;
|
||||
|
||||
if (thd->to_size < thd->to_len + XB_CRYPT_HASH_LEN) {
|
||||
thd->to = (uchar *) my_realloc(
|
||||
thd->to,
|
||||
thd->to_len + XB_CRYPT_HASH_LEN,
|
||||
MYF(MY_FAE | MY_ALLOW_ZERO_PTR));
|
||||
thd->to_size = thd->to_len;
|
||||
}
|
||||
|
||||
CHECK_BUF_SIZE(ptr, 8, buf, len);
|
||||
tmp = uint8korr(ptr); /* encrypted size */
|
||||
ptr += 8;
|
||||
if (tmp > INT_MAX) {
|
||||
msg("%s:%s: invalid encrypted size at offset 0x%llx.\n",
|
||||
my_progname, __FUNCTION__, thd->offset);
|
||||
result = XB_CRYPT_READ_ERROR;
|
||||
goto exit;
|
||||
}
|
||||
thd->offset += 8;
|
||||
thd->from_len = (size_t)tmp;
|
||||
|
||||
xb_a(thd->from_len <= thd->to_len + XB_CRYPT_HASH_LEN);
|
||||
|
||||
CHECK_BUF_SIZE(ptr, 4, buf, len);
|
||||
checksum_exp = uint4korr(ptr); /* checksum */
|
||||
ptr += 4;
|
||||
thd->offset += 4;
|
||||
|
||||
/* iv size */
|
||||
if (version == 1) {
|
||||
thd->iv_len = 0;
|
||||
thd->iv = NULL;
|
||||
} else {
|
||||
CHECK_BUF_SIZE(ptr, 8, buf, len);
|
||||
|
||||
tmp = uint8korr(ptr);
|
||||
if (tmp > INT_MAX) {
|
||||
msg("%s:%s: invalid iv size at offset 0x%llx.\n",
|
||||
my_progname, __FUNCTION__, thd->offset);
|
||||
result = XB_CRYPT_READ_ERROR;
|
||||
goto exit;
|
||||
}
|
||||
ptr += 8;
|
||||
thd->offset += 8;
|
||||
thd->iv_len = (size_t)tmp;
|
||||
}
|
||||
|
||||
if (thd->iv_len > 0) {
|
||||
CHECK_BUF_SIZE(ptr, thd->iv_len, buf, len);
|
||||
thd->iv = ptr;
|
||||
ptr += thd->iv_len;
|
||||
}
|
||||
|
||||
/* for version euqals 2 we need to read in the iv data but do not init
|
||||
CTR with it */
|
||||
if (version == 2) {
|
||||
thd->iv_len = 0;
|
||||
thd->iv = 0;
|
||||
}
|
||||
|
||||
if (thd->from_len > 0) {
|
||||
CHECK_BUF_SIZE(ptr, thd->from_len, buf, len);
|
||||
thd->from = ptr;
|
||||
ptr += thd->from_len;
|
||||
}
|
||||
|
||||
xb_ad(thd->from_len <= thd->to_len);
|
||||
|
||||
checksum = crc32_iso3309(0, thd->from, thd->from_len);
|
||||
if (checksum != checksum_exp) {
|
||||
msg("%s:%s invalid checksum at offset 0x%llx, "
|
||||
"expected 0x%lx, actual 0x%lx.\n", my_progname,
|
||||
__FUNCTION__, thd->offset, checksum_exp, checksum);
|
||||
result = XB_CRYPT_READ_ERROR;
|
||||
goto exit;
|
||||
}
|
||||
|
||||
thd->offset += thd->from_len;
|
||||
|
||||
thd->hash_appended = version > 2;
|
||||
|
||||
exit:
|
||||
|
||||
*bytes_processed = (size_t) (ptr - buf);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
static
|
||||
int
|
||||
decrypt_write(ds_file_t *file, const void *buf, size_t len)
|
||||
{
|
||||
ds_decrypt_file_t *crypt_file;
|
||||
ds_decrypt_ctxt_t *crypt_ctxt;
|
||||
crypt_thread_ctxt_t *threads;
|
||||
crypt_thread_ctxt_t *thd;
|
||||
uint nthreads;
|
||||
uint i;
|
||||
size_t bytes_processed;
|
||||
xb_rcrypt_result_t parse_result = XB_CRYPT_READ_CHUNK;
|
||||
my_bool err = FALSE;
|
||||
|
||||
crypt_file = (ds_decrypt_file_t *) file->ptr;
|
||||
crypt_ctxt = crypt_file->crypt_ctxt;
|
||||
|
||||
threads = crypt_ctxt->threads;
|
||||
nthreads = crypt_ctxt->nthreads;
|
||||
|
||||
if (crypt_file->buf_len > 0) {
|
||||
thd = threads;
|
||||
|
||||
pthread_mutex_lock(&thd->ctrl_mutex);
|
||||
|
||||
do {
|
||||
if (parse_result == XB_CRYPT_READ_INCOMPLETE) {
|
||||
crypt_file->buf_size = crypt_file->buf_size * 2;
|
||||
crypt_file->buf = (uchar *) my_realloc(
|
||||
crypt_file->buf,
|
||||
crypt_file->buf_size,
|
||||
MYF(MY_FAE|MY_ALLOW_ZERO_PTR));
|
||||
}
|
||||
|
||||
memcpy(crypt_file->buf + crypt_file->buf_len,
|
||||
buf, MY_MIN(crypt_file->buf_size -
|
||||
crypt_file->buf_len, len));
|
||||
|
||||
parse_result = parse_xbcrypt_chunk(
|
||||
thd, crypt_file->buf,
|
||||
crypt_file->buf_size, &bytes_processed);
|
||||
|
||||
if (parse_result == XB_CRYPT_READ_ERROR) {
|
||||
pthread_mutex_unlock(&thd->ctrl_mutex);
|
||||
return 1;
|
||||
}
|
||||
|
||||
} while (parse_result == XB_CRYPT_READ_INCOMPLETE &&
|
||||
crypt_file->buf_size < len);
|
||||
|
||||
if (parse_result != XB_CRYPT_READ_CHUNK) {
|
||||
msg("decrypt: incomplete data.\n");
|
||||
pthread_mutex_unlock(&thd->ctrl_mutex);
|
||||
return 1;
|
||||
}
|
||||
|
||||
pthread_mutex_lock(&thd->data_mutex);
|
||||
thd->data_avail = TRUE;
|
||||
pthread_cond_signal(&thd->data_cond);
|
||||
pthread_mutex_unlock(&thd->data_mutex);
|
||||
|
||||
len -= bytes_processed - crypt_file->buf_len;
|
||||
buf += bytes_processed - crypt_file->buf_len;
|
||||
|
||||
/* reap */
|
||||
|
||||
pthread_mutex_lock(&thd->data_mutex);
|
||||
while (thd->data_avail == TRUE) {
|
||||
pthread_cond_wait(&thd->data_cond,
|
||||
&thd->data_mutex);
|
||||
}
|
||||
|
||||
if (thd->failed) {
|
||||
msg("decrypt: failed to decrypt chunk.\n");
|
||||
err = TRUE;
|
||||
}
|
||||
|
||||
xb_a(thd->to_len > 0);
|
||||
|
||||
if (!err &&
|
||||
ds_write(crypt_file->dest_file, thd->to, thd->to_len)) {
|
||||
msg("decrypt: write to destination failed.\n");
|
||||
err = TRUE;
|
||||
}
|
||||
|
||||
crypt_file->bytes_processed += thd->from_len;
|
||||
|
||||
pthread_mutex_unlock(&thd->data_mutex);
|
||||
pthread_mutex_unlock(&thd->ctrl_mutex);
|
||||
|
||||
crypt_file->buf_len = 0;
|
||||
|
||||
if (err) {
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
while (parse_result == XB_CRYPT_READ_CHUNK && len > 0) {
|
||||
uint max_thread;
|
||||
|
||||
for (i = 0; i < nthreads; i++) {
|
||||
thd = threads + i;
|
||||
|
||||
pthread_mutex_lock(&thd->ctrl_mutex);
|
||||
|
||||
parse_result = parse_xbcrypt_chunk(
|
||||
thd, buf, len, &bytes_processed);
|
||||
|
||||
if (parse_result == XB_CRYPT_READ_ERROR) {
|
||||
pthread_mutex_unlock(&thd->ctrl_mutex);
|
||||
err = TRUE;
|
||||
break;
|
||||
}
|
||||
|
||||
thd->parse_result = parse_result;
|
||||
|
||||
if (parse_result != XB_CRYPT_READ_CHUNK) {
|
||||
pthread_mutex_unlock(&thd->ctrl_mutex);
|
||||
break;
|
||||
}
|
||||
|
||||
pthread_mutex_lock(&thd->data_mutex);
|
||||
thd->data_avail = TRUE;
|
||||
pthread_cond_signal(&thd->data_cond);
|
||||
pthread_mutex_unlock(&thd->data_mutex);
|
||||
|
||||
len -= bytes_processed;
|
||||
buf += bytes_processed;
|
||||
}
|
||||
|
||||
max_thread = (i < nthreads) ? i : nthreads - 1;
|
||||
|
||||
/* Reap and write decrypted data */
|
||||
for (i = 0; i <= max_thread; i++) {
|
||||
thd = threads + i;
|
||||
|
||||
if (thd->parse_result != XB_CRYPT_READ_CHUNK) {
|
||||
break;
|
||||
}
|
||||
|
||||
pthread_mutex_lock(&thd->data_mutex);
|
||||
while (thd->data_avail == TRUE) {
|
||||
pthread_cond_wait(&thd->data_cond,
|
||||
&thd->data_mutex);
|
||||
}
|
||||
|
||||
if (thd->failed) {
|
||||
msg("decrypt: failed to decrypt chunk.\n");
|
||||
err = TRUE;
|
||||
}
|
||||
|
||||
xb_a(thd->to_len > 0);
|
||||
|
||||
if (!err && ds_write(crypt_file->dest_file, thd->to,
|
||||
thd->to_len)) {
|
||||
msg("decrypt: write to destination failed.\n");
|
||||
err = TRUE;
|
||||
}
|
||||
|
||||
crypt_file->bytes_processed += thd->from_len;
|
||||
|
||||
pthread_mutex_unlock(&thd->data_mutex);
|
||||
pthread_mutex_unlock(&thd->ctrl_mutex);
|
||||
}
|
||||
|
||||
if (err) {
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
if (parse_result == XB_CRYPT_READ_INCOMPLETE && len > 0) {
|
||||
crypt_file->buf_len = len;
|
||||
if (crypt_file->buf_size < len) {
|
||||
crypt_file->buf = (uchar *) my_realloc(
|
||||
crypt_file->buf,
|
||||
crypt_file->buf_len,
|
||||
MYF(MY_FAE | MY_ALLOW_ZERO_PTR));
|
||||
crypt_file->buf_size = len;
|
||||
}
|
||||
memcpy(crypt_file->buf, buf, len);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static
|
||||
int
|
||||
decrypt_close(ds_file_t *file)
|
||||
{
|
||||
ds_decrypt_file_t *crypt_file;
|
||||
ds_file_t *dest_file;
|
||||
int rc = 0;
|
||||
|
||||
crypt_file = (ds_decrypt_file_t *) file->ptr;
|
||||
dest_file = crypt_file->dest_file;
|
||||
|
||||
if (ds_close(dest_file)) {
|
||||
rc = 1;
|
||||
}
|
||||
|
||||
my_free(crypt_file->buf);
|
||||
my_free(file);
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
static
|
||||
void
|
||||
decrypt_deinit(ds_ctxt_t *ctxt)
|
||||
{
|
||||
ds_decrypt_ctxt_t *crypt_ctxt;
|
||||
|
||||
xb_ad(ctxt->pipe_ctxt != NULL);
|
||||
|
||||
crypt_ctxt = (ds_decrypt_ctxt_t *) ctxt->ptr;
|
||||
|
||||
destroy_worker_threads(crypt_ctxt->threads, crypt_ctxt->nthreads);
|
||||
|
||||
my_free(ctxt->root);
|
||||
my_free(ctxt);
|
||||
}
|
||||
|
||||
static
|
||||
crypt_thread_ctxt_t *
|
||||
create_worker_threads(uint n)
|
||||
{
|
||||
crypt_thread_ctxt_t *threads;
|
||||
uint i;
|
||||
|
||||
threads = (crypt_thread_ctxt_t *)
|
||||
my_malloc(sizeof(crypt_thread_ctxt_t) * n,
|
||||
MYF(MY_FAE | MY_ZEROFILL));
|
||||
|
||||
for (i = 0; i < n; i++) {
|
||||
crypt_thread_ctxt_t *thd = threads + i;
|
||||
|
||||
thd->num = i + 1;
|
||||
|
||||
/* Initialize the control mutex and condition var */
|
||||
if (pthread_mutex_init(&thd->ctrl_mutex, NULL) ||
|
||||
pthread_cond_init(&thd->ctrl_cond, NULL)) {
|
||||
goto err;
|
||||
}
|
||||
|
||||
/* Initialize and data mutex and condition var */
|
||||
if (pthread_mutex_init(&thd->data_mutex, NULL) ||
|
||||
pthread_cond_init(&thd->data_cond, NULL)) {
|
||||
goto err;
|
||||
}
|
||||
|
||||
xb_crypt_cipher_open(&thd->cipher_handle);
|
||||
|
||||
pthread_mutex_lock(&thd->ctrl_mutex);
|
||||
|
||||
if (pthread_create(&thd->id, NULL, decrypt_worker_thread_func,
|
||||
thd)) {
|
||||
msg("decrypt: pthread_create() failed: "
|
||||
"errno = %d\n", errno);
|
||||
goto err;
|
||||
}
|
||||
}
|
||||
|
||||
/* Wait for the threads to start */
|
||||
for (i = 0; i < n; i++) {
|
||||
crypt_thread_ctxt_t *thd = threads + i;
|
||||
|
||||
while (thd->started == FALSE)
|
||||
pthread_cond_wait(&thd->ctrl_cond, &thd->ctrl_mutex);
|
||||
pthread_mutex_unlock(&thd->ctrl_mutex);
|
||||
}
|
||||
|
||||
return threads;
|
||||
|
||||
err:
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static
|
||||
void
|
||||
destroy_worker_threads(crypt_thread_ctxt_t *threads, uint n)
|
||||
{
|
||||
uint i;
|
||||
|
||||
for (i = 0; i < n; i++) {
|
||||
crypt_thread_ctxt_t *thd = threads + i;
|
||||
|
||||
pthread_mutex_lock(&thd->data_mutex);
|
||||
threads[i].cancelled = TRUE;
|
||||
pthread_cond_signal(&thd->data_cond);
|
||||
pthread_mutex_unlock(&thd->data_mutex);
|
||||
|
||||
pthread_join(thd->id, NULL);
|
||||
|
||||
pthread_cond_destroy(&thd->data_cond);
|
||||
pthread_mutex_destroy(&thd->data_mutex);
|
||||
pthread_cond_destroy(&thd->ctrl_cond);
|
||||
pthread_mutex_destroy(&thd->ctrl_mutex);
|
||||
|
||||
xb_crypt_cipher_close(thd->cipher_handle);
|
||||
|
||||
my_free(thd->to);
|
||||
}
|
||||
|
||||
my_free(threads);
|
||||
}
|
||||
|
||||
static
|
||||
void *
|
||||
decrypt_worker_thread_func(void *arg)
|
||||
{
|
||||
crypt_thread_ctxt_t *thd = (crypt_thread_ctxt_t *) arg;
|
||||
|
||||
pthread_mutex_lock(&thd->ctrl_mutex);
|
||||
|
||||
pthread_mutex_lock(&thd->data_mutex);
|
||||
|
||||
thd->started = TRUE;
|
||||
pthread_cond_signal(&thd->ctrl_cond);
|
||||
|
||||
pthread_mutex_unlock(&thd->ctrl_mutex);
|
||||
|
||||
while (1) {
|
||||
thd->data_avail = FALSE;
|
||||
pthread_cond_signal(&thd->data_cond);
|
||||
|
||||
while (!thd->data_avail && !thd->cancelled) {
|
||||
pthread_cond_wait(&thd->data_cond, &thd->data_mutex);
|
||||
}
|
||||
|
||||
if (thd->cancelled)
|
||||
break;
|
||||
|
||||
if (xb_crypt_decrypt(thd->cipher_handle, thd->from,
|
||||
thd->from_len, thd->to, &thd->to_len,
|
||||
thd->iv, thd->iv_len,
|
||||
thd->hash_appended)) {
|
||||
thd->failed = TRUE;
|
||||
continue;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
pthread_mutex_unlock(&thd->data_mutex);
|
||||
|
||||
return NULL;
|
||||
}
|
30
extra/mariabackup/ds_decrypt.h
Normal file
30
extra/mariabackup/ds_decrypt.h
Normal file
|
@ -0,0 +1,30 @@
|
|||
/******************************************************
|
||||
Copyright (c) 2017 Percona LLC and/or its affiliates.
|
||||
|
||||
Encryption interface for XtraBackup.
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; version 2 of the License.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
|
||||
|
||||
*******************************************************/
|
||||
|
||||
#ifndef DS_DECRYPT_H
|
||||
#define DS_DECRYPT_H
|
||||
|
||||
#include "datasink.h"
|
||||
|
||||
extern datasink_t datasink_decrypt;
|
||||
|
||||
extern int ds_decrypt_encrypt_threads;
|
||||
|
||||
#endif
|
446
extra/mariabackup/ds_encrypt.c
Normal file
446
extra/mariabackup/ds_encrypt.c
Normal file
|
@ -0,0 +1,446 @@
|
|||
/******************************************************
|
||||
Copyright (c) 2013 Percona LLC and/or its affiliates.
|
||||
|
||||
Encryption datasink implementation for XtraBackup.
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; version 2 of the License.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
|
||||
|
||||
*******************************************************/
|
||||
|
||||
|
||||
#include <my_base.h>
|
||||
#include "common.h"
|
||||
#include "datasink.h"
|
||||
#include "xbcrypt_common.h"
|
||||
#ifdef HAVE_GRYPT
|
||||
#include "xbcrypt.h"
|
||||
|
||||
#define XB_CRYPT_CHUNK_SIZE ((size_t) (ds_encrypt_encrypt_chunk_size))
|
||||
|
||||
typedef struct {
|
||||
pthread_t id;
|
||||
uint num;
|
||||
pthread_mutex_t ctrl_mutex;
|
||||
pthread_cond_t ctrl_cond;
|
||||
pthread_mutex_t data_mutex;
|
||||
pthread_cond_t data_cond;
|
||||
my_bool started;
|
||||
my_bool data_avail;
|
||||
my_bool cancelled;
|
||||
const uchar *from;
|
||||
size_t from_len;
|
||||
uchar *to;
|
||||
uchar *iv;
|
||||
size_t to_len;
|
||||
gcry_cipher_hd_t cipher_handle;
|
||||
} crypt_thread_ctxt_t;
|
||||
|
||||
typedef struct {
|
||||
crypt_thread_ctxt_t *threads;
|
||||
uint nthreads;
|
||||
} ds_encrypt_ctxt_t;
|
||||
|
||||
typedef struct {
|
||||
xb_wcrypt_t *xbcrypt_file;
|
||||
ds_encrypt_ctxt_t *crypt_ctxt;
|
||||
size_t bytes_processed;
|
||||
ds_file_t *dest_file;
|
||||
} ds_encrypt_file_t;
|
||||
|
||||
/* Encryption options */
|
||||
uint ds_encrypt_encrypt_threads;
|
||||
ulonglong ds_encrypt_encrypt_chunk_size;
|
||||
|
||||
static ds_ctxt_t *encrypt_init(const char *root);
|
||||
static ds_file_t *encrypt_open(ds_ctxt_t *ctxt, const char *path,
|
||||
MY_STAT *mystat);
|
||||
static int encrypt_write(ds_file_t *file, const void *buf, size_t len);
|
||||
static int encrypt_close(ds_file_t *file);
|
||||
static void encrypt_deinit(ds_ctxt_t *ctxt);
|
||||
|
||||
datasink_t datasink_encrypt = {
|
||||
&encrypt_init,
|
||||
&encrypt_open,
|
||||
&encrypt_write,
|
||||
&encrypt_close,
|
||||
&encrypt_deinit
|
||||
};
|
||||
|
||||
static crypt_thread_ctxt_t *create_worker_threads(uint n);
|
||||
static void destroy_worker_threads(crypt_thread_ctxt_t *threads, uint n);
|
||||
static void *encrypt_worker_thread_func(void *arg);
|
||||
|
||||
static uint encrypt_iv_len = 0;
|
||||
|
||||
static
|
||||
ssize_t
|
||||
my_xb_crypt_write_callback(void *userdata, const void *buf, size_t len)
|
||||
{
|
||||
ds_encrypt_file_t *encrypt_file;
|
||||
|
||||
encrypt_file = (ds_encrypt_file_t *) userdata;
|
||||
|
||||
xb_ad(encrypt_file != NULL);
|
||||
xb_ad(encrypt_file->dest_file != NULL);
|
||||
|
||||
if (!ds_write(encrypt_file->dest_file, buf, len)) {
|
||||
return len;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
static
|
||||
ds_ctxt_t *
|
||||
encrypt_init(const char *root)
|
||||
{
|
||||
ds_ctxt_t *ctxt;
|
||||
ds_encrypt_ctxt_t *encrypt_ctxt;
|
||||
crypt_thread_ctxt_t *threads;
|
||||
|
||||
if (xb_crypt_init(&encrypt_iv_len)) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* Create and initialize the worker threads */
|
||||
threads = create_worker_threads(ds_encrypt_encrypt_threads);
|
||||
if (threads == NULL) {
|
||||
msg("encrypt: failed to create worker threads.\n");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
ctxt = (ds_ctxt_t *) my_malloc(sizeof(ds_ctxt_t) +
|
||||
sizeof(ds_encrypt_ctxt_t),
|
||||
MYF(MY_FAE));
|
||||
|
||||
encrypt_ctxt = (ds_encrypt_ctxt_t *) (ctxt + 1);
|
||||
encrypt_ctxt->threads = threads;
|
||||
encrypt_ctxt->nthreads = ds_encrypt_encrypt_threads;
|
||||
|
||||
ctxt->ptr = encrypt_ctxt;
|
||||
ctxt->root = my_strdup(root, MYF(MY_FAE));
|
||||
|
||||
return ctxt;
|
||||
}
|
||||
|
||||
static
|
||||
ds_file_t *
|
||||
encrypt_open(ds_ctxt_t *ctxt, const char *path, MY_STAT *mystat)
|
||||
{
|
||||
ds_ctxt_t *dest_ctxt;
|
||||
|
||||
ds_encrypt_ctxt_t *crypt_ctxt;
|
||||
ds_encrypt_file_t *crypt_file;
|
||||
|
||||
char new_name[FN_REFLEN];
|
||||
ds_file_t *file;
|
||||
|
||||
xb_ad(ctxt->pipe_ctxt != NULL);
|
||||
dest_ctxt = ctxt->pipe_ctxt;
|
||||
|
||||
crypt_ctxt = (ds_encrypt_ctxt_t *) ctxt->ptr;
|
||||
|
||||
|
||||
file = (ds_file_t *) my_malloc(sizeof(ds_file_t) +
|
||||
sizeof(ds_encrypt_file_t),
|
||||
MYF(MY_FAE|MY_ZEROFILL));
|
||||
|
||||
crypt_file = (ds_encrypt_file_t *) (file + 1);
|
||||
|
||||
/* Append the .xbcrypt extension to the filename */
|
||||
fn_format(new_name, path, "", ".xbcrypt", MYF(MY_APPEND_EXT));
|
||||
crypt_file->dest_file = ds_open(dest_ctxt, new_name, mystat);
|
||||
if (crypt_file->dest_file == NULL) {
|
||||
msg("encrypt: ds_open(\"%s\") failed.\n", new_name);
|
||||
goto err;
|
||||
}
|
||||
|
||||
crypt_file->crypt_ctxt = crypt_ctxt;
|
||||
crypt_file->xbcrypt_file = xb_crypt_write_open(crypt_file,
|
||||
my_xb_crypt_write_callback);
|
||||
|
||||
if (crypt_file->xbcrypt_file == NULL) {
|
||||
msg("encrypt: xb_crypt_write_open() failed.\n");
|
||||
goto err;
|
||||
}
|
||||
|
||||
|
||||
file->ptr = crypt_file;
|
||||
file->path = crypt_file->dest_file->path;
|
||||
|
||||
return file;
|
||||
|
||||
err:
|
||||
if (crypt_file->dest_file) {
|
||||
ds_close(crypt_file->dest_file);
|
||||
}
|
||||
my_free(file);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static
|
||||
int
|
||||
encrypt_write(ds_file_t *file, const void *buf, size_t len)
|
||||
{
|
||||
ds_encrypt_file_t *crypt_file;
|
||||
ds_encrypt_ctxt_t *crypt_ctxt;
|
||||
crypt_thread_ctxt_t *threads;
|
||||
crypt_thread_ctxt_t *thd;
|
||||
uint nthreads;
|
||||
uint i;
|
||||
const uchar *ptr;
|
||||
|
||||
crypt_file = (ds_encrypt_file_t *) file->ptr;
|
||||
crypt_ctxt = crypt_file->crypt_ctxt;
|
||||
|
||||
threads = crypt_ctxt->threads;
|
||||
nthreads = crypt_ctxt->nthreads;
|
||||
|
||||
ptr = (const uchar *) buf;
|
||||
while (len > 0) {
|
||||
uint max_thread;
|
||||
|
||||
/* Send data to worker threads for encryption */
|
||||
for (i = 0; i < nthreads; i++) {
|
||||
size_t chunk_len;
|
||||
|
||||
thd = threads + i;
|
||||
|
||||
pthread_mutex_lock(&thd->ctrl_mutex);
|
||||
|
||||
chunk_len = (len > XB_CRYPT_CHUNK_SIZE) ?
|
||||
XB_CRYPT_CHUNK_SIZE : len;
|
||||
thd->from = ptr;
|
||||
thd->from_len = chunk_len;
|
||||
|
||||
pthread_mutex_lock(&thd->data_mutex);
|
||||
thd->data_avail = TRUE;
|
||||
pthread_cond_signal(&thd->data_cond);
|
||||
pthread_mutex_unlock(&thd->data_mutex);
|
||||
|
||||
len -= chunk_len;
|
||||
if (len == 0) {
|
||||
break;
|
||||
}
|
||||
ptr += chunk_len;
|
||||
}
|
||||
|
||||
max_thread = (i < nthreads) ? i : nthreads - 1;
|
||||
|
||||
/* Reap and stream the encrypted data */
|
||||
for (i = 0; i <= max_thread; i++) {
|
||||
thd = threads + i;
|
||||
|
||||
pthread_mutex_lock(&thd->data_mutex);
|
||||
while (thd->data_avail == TRUE) {
|
||||
pthread_cond_wait(&thd->data_cond,
|
||||
&thd->data_mutex);
|
||||
}
|
||||
|
||||
xb_a(threads[i].to_len > 0);
|
||||
|
||||
if (xb_crypt_write_chunk(crypt_file->xbcrypt_file,
|
||||
threads[i].to,
|
||||
threads[i].from_len +
|
||||
XB_CRYPT_HASH_LEN,
|
||||
threads[i].to_len,
|
||||
threads[i].iv,
|
||||
encrypt_iv_len)) {
|
||||
msg("encrypt: write to the destination file "
|
||||
"failed.\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
crypt_file->bytes_processed += threads[i].from_len;
|
||||
|
||||
pthread_mutex_unlock(&threads[i].data_mutex);
|
||||
pthread_mutex_unlock(&threads[i].ctrl_mutex);
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static
|
||||
int
|
||||
encrypt_close(ds_file_t *file)
|
||||
{
|
||||
ds_encrypt_file_t *crypt_file;
|
||||
ds_file_t *dest_file;
|
||||
int rc = 0;
|
||||
|
||||
crypt_file = (ds_encrypt_file_t *) file->ptr;
|
||||
dest_file = crypt_file->dest_file;
|
||||
|
||||
rc = xb_crypt_write_close(crypt_file->xbcrypt_file);
|
||||
|
||||
if (ds_close(dest_file)) {
|
||||
rc = 1;
|
||||
}
|
||||
|
||||
my_free(file);
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
static
|
||||
void
|
||||
encrypt_deinit(ds_ctxt_t *ctxt)
|
||||
{
|
||||
ds_encrypt_ctxt_t *crypt_ctxt;
|
||||
|
||||
xb_ad(ctxt->pipe_ctxt != NULL);
|
||||
|
||||
crypt_ctxt = (ds_encrypt_ctxt_t *) ctxt->ptr;
|
||||
|
||||
destroy_worker_threads(crypt_ctxt->threads, crypt_ctxt->nthreads);
|
||||
|
||||
my_free(ctxt->root);
|
||||
my_free(ctxt);
|
||||
}
|
||||
|
||||
static
|
||||
crypt_thread_ctxt_t *
|
||||
create_worker_threads(uint n)
|
||||
{
|
||||
crypt_thread_ctxt_t *threads;
|
||||
uint i;
|
||||
|
||||
threads = (crypt_thread_ctxt_t *)
|
||||
my_malloc(sizeof(crypt_thread_ctxt_t) * n, MYF(MY_FAE));
|
||||
|
||||
for (i = 0; i < n; i++) {
|
||||
crypt_thread_ctxt_t *thd = threads + i;
|
||||
|
||||
thd->num = i + 1;
|
||||
thd->started = FALSE;
|
||||
thd->cancelled = FALSE;
|
||||
thd->data_avail = FALSE;
|
||||
|
||||
thd->to = (uchar *) my_malloc(XB_CRYPT_CHUNK_SIZE +
|
||||
XB_CRYPT_HASH_LEN, MYF(MY_FAE));
|
||||
|
||||
thd->iv = (uchar *) my_malloc(encrypt_iv_len, MYF(MY_FAE));
|
||||
|
||||
/* Initialize the control mutex and condition var */
|
||||
if (pthread_mutex_init(&thd->ctrl_mutex, NULL) ||
|
||||
pthread_cond_init(&thd->ctrl_cond, NULL)) {
|
||||
goto err;
|
||||
}
|
||||
|
||||
/* Initialize and data mutex and condition var */
|
||||
if (pthread_mutex_init(&thd->data_mutex, NULL) ||
|
||||
pthread_cond_init(&thd->data_cond, NULL)) {
|
||||
goto err;
|
||||
}
|
||||
|
||||
if (xb_crypt_cipher_open(&thd->cipher_handle)) {
|
||||
goto err;
|
||||
}
|
||||
|
||||
pthread_mutex_lock(&thd->ctrl_mutex);
|
||||
|
||||
if (pthread_create(&thd->id, NULL, encrypt_worker_thread_func,
|
||||
thd)) {
|
||||
msg("encrypt: pthread_create() failed: "
|
||||
"errno = %d\n", errno);
|
||||
goto err;
|
||||
}
|
||||
}
|
||||
|
||||
/* Wait for the threads to start */
|
||||
for (i = 0; i < n; i++) {
|
||||
crypt_thread_ctxt_t *thd = threads + i;
|
||||
|
||||
while (thd->started == FALSE)
|
||||
pthread_cond_wait(&thd->ctrl_cond, &thd->ctrl_mutex);
|
||||
pthread_mutex_unlock(&thd->ctrl_mutex);
|
||||
}
|
||||
|
||||
return threads;
|
||||
|
||||
err:
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static
|
||||
void
|
||||
destroy_worker_threads(crypt_thread_ctxt_t *threads, uint n)
|
||||
{
|
||||
uint i;
|
||||
|
||||
for (i = 0; i < n; i++) {
|
||||
crypt_thread_ctxt_t *thd = threads + i;
|
||||
|
||||
pthread_mutex_lock(&thd->data_mutex);
|
||||
threads[i].cancelled = TRUE;
|
||||
pthread_cond_signal(&thd->data_cond);
|
||||
pthread_mutex_unlock(&thd->data_mutex);
|
||||
|
||||
pthread_join(thd->id, NULL);
|
||||
|
||||
pthread_cond_destroy(&thd->data_cond);
|
||||
pthread_mutex_destroy(&thd->data_mutex);
|
||||
pthread_cond_destroy(&thd->ctrl_cond);
|
||||
pthread_mutex_destroy(&thd->ctrl_mutex);
|
||||
|
||||
xb_crypt_cipher_close(thd->cipher_handle);
|
||||
|
||||
my_free(thd->to);
|
||||
my_free(thd->iv);
|
||||
}
|
||||
|
||||
my_free(threads);
|
||||
}
|
||||
|
||||
static
|
||||
void *
|
||||
encrypt_worker_thread_func(void *arg)
|
||||
{
|
||||
crypt_thread_ctxt_t *thd = (crypt_thread_ctxt_t *) arg;
|
||||
|
||||
pthread_mutex_lock(&thd->ctrl_mutex);
|
||||
|
||||
pthread_mutex_lock(&thd->data_mutex);
|
||||
|
||||
thd->started = TRUE;
|
||||
pthread_cond_signal(&thd->ctrl_cond);
|
||||
|
||||
pthread_mutex_unlock(&thd->ctrl_mutex);
|
||||
|
||||
while (1) {
|
||||
thd->data_avail = FALSE;
|
||||
pthread_cond_signal(&thd->data_cond);
|
||||
|
||||
while (!thd->data_avail && !thd->cancelled) {
|
||||
pthread_cond_wait(&thd->data_cond, &thd->data_mutex);
|
||||
}
|
||||
|
||||
if (thd->cancelled)
|
||||
break;
|
||||
|
||||
thd->to_len = thd->from_len;
|
||||
|
||||
if (xb_crypt_encrypt(thd->cipher_handle, thd->from,
|
||||
thd->from_len, thd->to, &thd->to_len,
|
||||
thd->iv)) {
|
||||
thd->to_len = 0;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
pthread_mutex_unlock(&thd->data_mutex);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
#endif /* HAVE_GCRYPT*/
|
33
extra/mariabackup/ds_encrypt.h
Normal file
33
extra/mariabackup/ds_encrypt.h
Normal file
|
@ -0,0 +1,33 @@
|
|||
/******************************************************
|
||||
Copyright (c) 2013 Percona LLC and/or its affiliates.
|
||||
|
||||
Encryption interface for XtraBackup.
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; version 2 of the License.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
|
||||
|
||||
*******************************************************/
|
||||
|
||||
#ifndef DS_ENCRYPT_H
|
||||
#define DS_ENCRYPT_H
|
||||
|
||||
#include "datasink.h"
|
||||
#ifdef HAVE_GCRYPT
|
||||
extern datasink_t datasink_encrypt;
|
||||
#endif
|
||||
/* Encryption options */
|
||||
extern uint ds_encrypt_encrypt_threads;
|
||||
extern ulonglong ds_encrypt_encrypt_chunk_size;
|
||||
|
||||
|
||||
#endif
|
151
extra/mariabackup/ds_local.c
Normal file
151
extra/mariabackup/ds_local.c
Normal file
|
@ -0,0 +1,151 @@
|
|||
/******************************************************
|
||||
Copyright (c) 2011-2013 Percona LLC and/or its affiliates.
|
||||
|
||||
Local datasink implementation for XtraBackup.
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; version 2 of the License.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
|
||||
|
||||
*******************************************************/
|
||||
|
||||
#include <mysql_version.h>
|
||||
#include <my_base.h>
|
||||
#include <mysys_err.h>
|
||||
#include "common.h"
|
||||
#include "datasink.h"
|
||||
|
||||
typedef struct {
|
||||
File fd;
|
||||
} ds_local_file_t;
|
||||
|
||||
static ds_ctxt_t *local_init(const char *root);
|
||||
static ds_file_t *local_open(ds_ctxt_t *ctxt, const char *path,
|
||||
MY_STAT *mystat);
|
||||
static int local_write(ds_file_t *file, const void *buf, size_t len);
|
||||
static int local_close(ds_file_t *file);
|
||||
static void local_deinit(ds_ctxt_t *ctxt);
|
||||
|
||||
datasink_t datasink_local = {
|
||||
&local_init,
|
||||
&local_open,
|
||||
&local_write,
|
||||
&local_close,
|
||||
&local_deinit
|
||||
};
|
||||
|
||||
static
|
||||
ds_ctxt_t *
|
||||
local_init(const char *root)
|
||||
{
|
||||
ds_ctxt_t *ctxt;
|
||||
|
||||
if (my_mkdir(root, 0777, MYF(0)) < 0
|
||||
&& my_errno != EEXIST && my_errno != EISDIR)
|
||||
{
|
||||
char errbuf[MYSYS_STRERROR_SIZE];
|
||||
my_strerror(errbuf, sizeof(errbuf),my_errno);
|
||||
my_error(EE_CANT_MKDIR, MYF(ME_BELL | ME_WAITTANG),
|
||||
root, my_errno,errbuf, my_errno);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
ctxt = my_malloc(sizeof(ds_ctxt_t), MYF(MY_FAE));
|
||||
|
||||
ctxt->root = my_strdup(root, MYF(MY_FAE));
|
||||
|
||||
return ctxt;
|
||||
}
|
||||
|
||||
static
|
||||
ds_file_t *
|
||||
local_open(ds_ctxt_t *ctxt, const char *path,
|
||||
MY_STAT *mystat __attribute__((unused)))
|
||||
{
|
||||
char fullpath[FN_REFLEN];
|
||||
char dirpath[FN_REFLEN];
|
||||
size_t dirpath_len;
|
||||
size_t path_len;
|
||||
ds_local_file_t *local_file;
|
||||
ds_file_t *file;
|
||||
File fd;
|
||||
|
||||
fn_format(fullpath, path, ctxt->root, "", MYF(MY_RELATIVE_PATH));
|
||||
|
||||
/* Create the directory if needed */
|
||||
dirname_part(dirpath, fullpath, &dirpath_len);
|
||||
if (my_mkdir(dirpath, 0777, MYF(0)) < 0 && my_errno != EEXIST) {
|
||||
char errbuf[MYSYS_STRERROR_SIZE];
|
||||
my_strerror(errbuf, sizeof(errbuf), my_errno);
|
||||
my_error(EE_CANT_MKDIR, MYF(ME_BELL | ME_WAITTANG),
|
||||
dirpath, my_errno, errbuf);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
fd = my_create(fullpath, 0, O_WRONLY | O_BINARY | O_EXCL | O_NOFOLLOW,
|
||||
MYF(MY_WME));
|
||||
if (fd < 0) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
path_len = strlen(fullpath) + 1; /* terminating '\0' */
|
||||
|
||||
file = (ds_file_t *) my_malloc(sizeof(ds_file_t) +
|
||||
sizeof(ds_local_file_t) +
|
||||
path_len,
|
||||
MYF(MY_FAE));
|
||||
local_file = (ds_local_file_t *) (file + 1);
|
||||
|
||||
local_file->fd = fd;
|
||||
|
||||
file->path = (char *) local_file + sizeof(ds_local_file_t);
|
||||
memcpy(file->path, fullpath, path_len);
|
||||
|
||||
file->ptr = local_file;
|
||||
|
||||
return file;
|
||||
}
|
||||
|
||||
static
|
||||
int
|
||||
local_write(ds_file_t *file, const void *buf, size_t len)
|
||||
{
|
||||
File fd = ((ds_local_file_t *) file->ptr)->fd;
|
||||
|
||||
if (!my_write(fd, buf, len, MYF(MY_WME | MY_NABP))) {
|
||||
posix_fadvise(fd, 0, 0, POSIX_FADV_DONTNEED);
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static
|
||||
int
|
||||
local_close(ds_file_t *file)
|
||||
{
|
||||
File fd = ((ds_local_file_t *) file->ptr)->fd;
|
||||
|
||||
my_free(file);
|
||||
|
||||
my_sync(fd, MYF(MY_WME));
|
||||
|
||||
return my_close(fd, MYF(MY_WME));
|
||||
}
|
||||
|
||||
static
|
||||
void
|
||||
local_deinit(ds_ctxt_t *ctxt)
|
||||
{
|
||||
my_free(ctxt->root);
|
||||
my_free(ctxt);
|
||||
}
|
28
extra/mariabackup/ds_local.h
Normal file
28
extra/mariabackup/ds_local.h
Normal file
|
@ -0,0 +1,28 @@
|
|||
/******************************************************
|
||||
Copyright (c) 2011-2013 Percona LLC and/or its affiliates.
|
||||
|
||||
Local datasink interface for XtraBackup.
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; version 2 of the License.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
|
||||
|
||||
*******************************************************/
|
||||
|
||||
#ifndef DS_LOCAL_H
|
||||
#define DS_LOCAL_H
|
||||
|
||||
#include "datasink.h"
|
||||
|
||||
extern datasink_t datasink_local;
|
||||
|
||||
#endif
|
121
extra/mariabackup/ds_stdout.c
Normal file
121
extra/mariabackup/ds_stdout.c
Normal file
|
@ -0,0 +1,121 @@
|
|||
/******************************************************
|
||||
Copyright (c) 2013 Percona LLC and/or its affiliates.
|
||||
|
||||
Local datasink implementation for XtraBackup.
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; version 2 of the License.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
|
||||
|
||||
*******************************************************/
|
||||
|
||||
#include <my_base.h>
|
||||
#include <mysys_err.h>
|
||||
#include "common.h"
|
||||
#include "datasink.h"
|
||||
|
||||
typedef struct {
|
||||
File fd;
|
||||
} ds_stdout_file_t;
|
||||
|
||||
static ds_ctxt_t *stdout_init(const char *root);
|
||||
static ds_file_t *stdout_open(ds_ctxt_t *ctxt, const char *path,
|
||||
MY_STAT *mystat);
|
||||
static int stdout_write(ds_file_t *file, const void *buf, size_t len);
|
||||
static int stdout_close(ds_file_t *file);
|
||||
static void stdout_deinit(ds_ctxt_t *ctxt);
|
||||
|
||||
datasink_t datasink_stdout = {
|
||||
&stdout_init,
|
||||
&stdout_open,
|
||||
&stdout_write,
|
||||
&stdout_close,
|
||||
&stdout_deinit
|
||||
};
|
||||
|
||||
static
|
||||
ds_ctxt_t *
|
||||
stdout_init(const char *root)
|
||||
{
|
||||
ds_ctxt_t *ctxt;
|
||||
|
||||
ctxt = my_malloc(sizeof(ds_ctxt_t), MYF(MY_FAE));
|
||||
|
||||
ctxt->root = my_strdup(root, MYF(MY_FAE));
|
||||
|
||||
return ctxt;
|
||||
}
|
||||
|
||||
static
|
||||
ds_file_t *
|
||||
stdout_open(ds_ctxt_t *ctxt __attribute__((unused)),
|
||||
const char *path __attribute__((unused)),
|
||||
MY_STAT *mystat __attribute__((unused)))
|
||||
{
|
||||
ds_stdout_file_t *stdout_file;
|
||||
ds_file_t *file;
|
||||
size_t pathlen;
|
||||
const char *fullpath = "<STDOUT>";
|
||||
|
||||
pathlen = strlen(fullpath) + 1;
|
||||
|
||||
file = (ds_file_t *) my_malloc(sizeof(ds_file_t) +
|
||||
sizeof(ds_stdout_file_t) +
|
||||
pathlen,
|
||||
MYF(MY_FAE));
|
||||
stdout_file = (ds_stdout_file_t *) (file + 1);
|
||||
|
||||
|
||||
#ifdef __WIN__
|
||||
setmode(fileno(stdout), _O_BINARY);
|
||||
#endif
|
||||
|
||||
stdout_file->fd = my_fileno(stdout);
|
||||
|
||||
file->path = (char *) stdout_file + sizeof(ds_stdout_file_t);
|
||||
memcpy(file->path, fullpath, pathlen);
|
||||
|
||||
file->ptr = stdout_file;
|
||||
|
||||
return file;
|
||||
}
|
||||
|
||||
static
|
||||
int
|
||||
stdout_write(ds_file_t *file, const void *buf, size_t len)
|
||||
{
|
||||
File fd = ((ds_stdout_file_t *) file->ptr)->fd;
|
||||
|
||||
if (!my_write(fd, buf, len, MYF(MY_WME | MY_NABP))) {
|
||||
posix_fadvise(fd, 0, 0, POSIX_FADV_DONTNEED);
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static
|
||||
int
|
||||
stdout_close(ds_file_t *file)
|
||||
{
|
||||
my_free(file);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static
|
||||
void
|
||||
stdout_deinit(ds_ctxt_t *ctxt)
|
||||
{
|
||||
my_free(ctxt->root);
|
||||
my_free(ctxt);
|
||||
}
|
28
extra/mariabackup/ds_stdout.h
Normal file
28
extra/mariabackup/ds_stdout.h
Normal file
|
@ -0,0 +1,28 @@
|
|||
/******************************************************
|
||||
Copyright (c) 2013 Percona LLC and/or its affiliates.
|
||||
|
||||
Local datasink interface for XtraBackup.
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; version 2 of the License.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
|
||||
|
||||
*******************************************************/
|
||||
|
||||
#ifndef DS_STDOUT_H
|
||||
#define DS_STDOUT_H
|
||||
|
||||
#include "datasink.h"
|
||||
|
||||
extern datasink_t datasink_stdout;
|
||||
|
||||
#endif
|
247
extra/mariabackup/ds_tmpfile.c
Normal file
247
extra/mariabackup/ds_tmpfile.c
Normal file
|
@ -0,0 +1,247 @@
|
|||
/******************************************************
|
||||
Copyright (c) 2012 Percona LLC and/or its affiliates.
|
||||
|
||||
tmpfile datasink for XtraBackup.
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; version 2 of the License.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
|
||||
|
||||
*******************************************************/
|
||||
|
||||
/* Do all writes to temporary files first, then pipe them to the specified
|
||||
datasink in a serialized way in deinit(). */
|
||||
|
||||
#include <my_base.h>
|
||||
#include "common.h"
|
||||
#include "datasink.h"
|
||||
|
||||
typedef struct {
|
||||
pthread_mutex_t mutex;
|
||||
LIST *file_list;
|
||||
} ds_tmpfile_ctxt_t;
|
||||
|
||||
typedef struct {
|
||||
LIST list;
|
||||
File fd;
|
||||
char *orig_path;
|
||||
MY_STAT mystat;
|
||||
ds_file_t *file;
|
||||
} ds_tmp_file_t;
|
||||
|
||||
static ds_ctxt_t *tmpfile_init(const char *root);
|
||||
static ds_file_t *tmpfile_open(ds_ctxt_t *ctxt, const char *path,
|
||||
MY_STAT *mystat);
|
||||
static int tmpfile_write(ds_file_t *file, const void *buf, size_t len);
|
||||
static int tmpfile_close(ds_file_t *file);
|
||||
static void tmpfile_deinit(ds_ctxt_t *ctxt);
|
||||
|
||||
datasink_t datasink_tmpfile = {
|
||||
&tmpfile_init,
|
||||
&tmpfile_open,
|
||||
&tmpfile_write,
|
||||
&tmpfile_close,
|
||||
&tmpfile_deinit
|
||||
};
|
||||
|
||||
|
||||
static ds_ctxt_t *
|
||||
tmpfile_init(const char *root)
|
||||
{
|
||||
ds_ctxt_t *ctxt;
|
||||
ds_tmpfile_ctxt_t *tmpfile_ctxt;
|
||||
|
||||
ctxt = my_malloc(sizeof(ds_ctxt_t) + sizeof(ds_tmpfile_ctxt_t),
|
||||
MYF(MY_FAE));
|
||||
tmpfile_ctxt = (ds_tmpfile_ctxt_t *) (ctxt + 1);
|
||||
tmpfile_ctxt->file_list = NULL;
|
||||
if (pthread_mutex_init(&tmpfile_ctxt->mutex, NULL)) {
|
||||
|
||||
my_free(ctxt);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
ctxt->ptr = tmpfile_ctxt;
|
||||
ctxt->root = my_strdup(root, MYF(MY_FAE));
|
||||
|
||||
return ctxt;
|
||||
}
|
||||
|
||||
static ds_file_t *
|
||||
tmpfile_open(ds_ctxt_t *ctxt, const char *path,
|
||||
MY_STAT *mystat)
|
||||
{
|
||||
ds_tmpfile_ctxt_t *tmpfile_ctxt;
|
||||
char tmp_path[FN_REFLEN];
|
||||
ds_tmp_file_t *tmp_file;
|
||||
ds_file_t *file;
|
||||
size_t path_len;
|
||||
File fd;
|
||||
|
||||
/* Create a temporary file in tmpdir. The file will be automatically
|
||||
removed on close. Code copied from mysql_tmpfile(). */
|
||||
fd = create_temp_file(tmp_path,xtrabackup_tmpdir,
|
||||
"xbtemp",
|
||||
#ifdef __WIN__
|
||||
O_BINARY | O_TRUNC | O_SEQUENTIAL |
|
||||
O_TEMPORARY | O_SHORT_LIVED |
|
||||
#endif /* __WIN__ */
|
||||
O_CREAT | O_EXCL | O_RDWR,
|
||||
MYF(MY_WME));
|
||||
|
||||
#ifndef __WIN__
|
||||
if (fd >= 0) {
|
||||
/* On Windows, open files cannot be removed, but files can be
|
||||
created with the O_TEMPORARY flag to the same effect
|
||||
("delete on close"). */
|
||||
unlink(tmp_path);
|
||||
}
|
||||
#endif /* !__WIN__ */
|
||||
|
||||
if (fd < 0) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
path_len = strlen(path) + 1; /* terminating '\0' */
|
||||
|
||||
file = (ds_file_t *) my_malloc(sizeof(ds_file_t) +
|
||||
sizeof(ds_tmp_file_t) + path_len,
|
||||
MYF(MY_FAE));
|
||||
|
||||
tmp_file = (ds_tmp_file_t *) (file + 1);
|
||||
tmp_file->file = file;
|
||||
memcpy(&tmp_file->mystat, mystat, sizeof(MY_STAT));
|
||||
/* Save a copy of 'path', since it may not be accessible later */
|
||||
tmp_file->orig_path = (char *) tmp_file + sizeof(ds_tmp_file_t);
|
||||
|
||||
tmp_file->fd = fd;
|
||||
memcpy(tmp_file->orig_path, path, path_len);
|
||||
|
||||
/* Store the real temporary file name in file->path */
|
||||
file->path = my_strdup(tmp_path, MYF(MY_FAE));
|
||||
file->ptr = tmp_file;
|
||||
|
||||
/* Store the file object in the list to be piped later */
|
||||
tmpfile_ctxt = (ds_tmpfile_ctxt_t *) ctxt->ptr;
|
||||
tmp_file->list.data = tmp_file;
|
||||
|
||||
pthread_mutex_lock(&tmpfile_ctxt->mutex);
|
||||
tmpfile_ctxt->file_list = list_add(tmpfile_ctxt->file_list,
|
||||
&tmp_file->list);
|
||||
pthread_mutex_unlock(&tmpfile_ctxt->mutex);
|
||||
|
||||
return file;
|
||||
}
|
||||
|
||||
static int
|
||||
tmpfile_write(ds_file_t *file, const void *buf, size_t len)
|
||||
{
|
||||
File fd = ((ds_tmp_file_t *) file->ptr)->fd;
|
||||
|
||||
if (!my_write(fd, buf, len, MYF(MY_WME | MY_NABP))) {
|
||||
posix_fadvise(fd, 0, 0, POSIX_FADV_DONTNEED);
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int
|
||||
tmpfile_close(ds_file_t *file)
|
||||
{
|
||||
/* Do nothing -- we will close (and thus remove) the file after piping
|
||||
it to the destination datasink in tmpfile_deinit(). */
|
||||
|
||||
my_free(file->path);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void
|
||||
tmpfile_deinit(ds_ctxt_t *ctxt)
|
||||
{
|
||||
LIST *list;
|
||||
ds_tmpfile_ctxt_t *tmpfile_ctxt;
|
||||
MY_STAT mystat;
|
||||
ds_tmp_file_t *tmp_file;
|
||||
ds_file_t *dst_file;
|
||||
ds_ctxt_t *pipe_ctxt;
|
||||
void *buf = NULL;
|
||||
const size_t buf_size = 10 * 1024 * 1024;
|
||||
size_t bytes;
|
||||
size_t offset;
|
||||
|
||||
pipe_ctxt = ctxt->pipe_ctxt;
|
||||
xb_a(pipe_ctxt != NULL);
|
||||
|
||||
buf = my_malloc(buf_size, MYF(MY_FAE));
|
||||
|
||||
tmpfile_ctxt = (ds_tmpfile_ctxt_t *) ctxt->ptr;
|
||||
list = tmpfile_ctxt->file_list;
|
||||
|
||||
/* Walk the files in the order they have been added */
|
||||
list = list_reverse(list);
|
||||
while (list != NULL) {
|
||||
tmp_file = list->data;
|
||||
/* Stat the file to replace size and mtime on the original
|
||||
* mystat struct */
|
||||
if (my_fstat(tmp_file->fd, &mystat, MYF(0))) {
|
||||
msg("error: my_fstat() failed.\n");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
tmp_file->mystat.st_size = mystat.st_size;
|
||||
tmp_file->mystat.st_mtime = mystat.st_mtime;
|
||||
|
||||
dst_file = ds_open(pipe_ctxt, tmp_file->orig_path,
|
||||
&tmp_file->mystat);
|
||||
if (dst_file == NULL) {
|
||||
msg("error: could not stream a temporary file to "
|
||||
"'%s'\n", tmp_file->orig_path);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
/* copy to the destination datasink */
|
||||
posix_fadvise(tmp_file->fd, 0, 0, POSIX_FADV_SEQUENTIAL);
|
||||
if (my_seek(tmp_file->fd, 0, SEEK_SET, MYF(0)) ==
|
||||
MY_FILEPOS_ERROR) {
|
||||
msg("error: my_seek() failed for '%s', errno = %d.\n",
|
||||
tmp_file->file->path, my_errno);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
offset = 0;
|
||||
while ((bytes = my_read(tmp_file->fd, buf, buf_size,
|
||||
MYF(MY_WME))) > 0) {
|
||||
posix_fadvise(tmp_file->fd, offset, buf_size, POSIX_FADV_DONTNEED);
|
||||
offset += buf_size;
|
||||
if (ds_write(dst_file, buf, bytes)) {
|
||||
msg("error: cannot write to stream for '%s'.\n",
|
||||
tmp_file->orig_path);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
}
|
||||
if (bytes == (size_t) -1) {
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
my_close(tmp_file->fd, MYF(MY_WME));
|
||||
ds_close(dst_file);
|
||||
|
||||
list = list_rest(list);
|
||||
my_free(tmp_file->file);
|
||||
}
|
||||
|
||||
pthread_mutex_destroy(&tmpfile_ctxt->mutex);
|
||||
|
||||
my_free(buf);
|
||||
my_free(ctxt->root);
|
||||
my_free(ctxt);
|
||||
}
|
30
extra/mariabackup/ds_tmpfile.h
Normal file
30
extra/mariabackup/ds_tmpfile.h
Normal file
|
@ -0,0 +1,30 @@
|
|||
/******************************************************
|
||||
Copyright (c) 2012 Percona LLC and/or its affiliates.
|
||||
|
||||
tmpfile datasink for XtraBackup.
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; version 2 of the License.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
|
||||
|
||||
*******************************************************/
|
||||
|
||||
#ifndef DS_TMPFILE_H
|
||||
#define DS_TMPFILE_H
|
||||
|
||||
#include "datasink.h"
|
||||
|
||||
extern datasink_t datasink_tmpfile;
|
||||
|
||||
extern MY_TMPDIR mysql_tmpdir_list;
|
||||
|
||||
#endif
|
223
extra/mariabackup/ds_xbstream.c
Normal file
223
extra/mariabackup/ds_xbstream.c
Normal file
|
@ -0,0 +1,223 @@
|
|||
/******************************************************
|
||||
Copyright (c) 2011-2013 Percona LLC and/or its affiliates.
|
||||
|
||||
Streaming implementation for XtraBackup.
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; version 2 of the License.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
|
||||
|
||||
*******************************************************/
|
||||
|
||||
#include <mysql_version.h>
|
||||
#include <my_base.h>
|
||||
#include "common.h"
|
||||
#include "datasink.h"
|
||||
#include "xbstream.h"
|
||||
|
||||
typedef struct {
|
||||
xb_wstream_t *xbstream;
|
||||
ds_file_t *dest_file;
|
||||
pthread_mutex_t mutex;
|
||||
} ds_stream_ctxt_t;
|
||||
|
||||
typedef struct {
|
||||
xb_wstream_file_t *xbstream_file;
|
||||
ds_stream_ctxt_t *stream_ctxt;
|
||||
} ds_stream_file_t;
|
||||
|
||||
/***********************************************************************
|
||||
General streaming interface */
|
||||
|
||||
static ds_ctxt_t *xbstream_init(const char *root);
|
||||
static ds_file_t *xbstream_open(ds_ctxt_t *ctxt, const char *path,
|
||||
MY_STAT *mystat);
|
||||
static int xbstream_write(ds_file_t *file, const void *buf, size_t len);
|
||||
static int xbstream_close(ds_file_t *file);
|
||||
static void xbstream_deinit(ds_ctxt_t *ctxt);
|
||||
|
||||
datasink_t datasink_xbstream = {
|
||||
&xbstream_init,
|
||||
&xbstream_open,
|
||||
&xbstream_write,
|
||||
&xbstream_close,
|
||||
&xbstream_deinit
|
||||
};
|
||||
|
||||
static
|
||||
ssize_t
|
||||
my_xbstream_write_callback(xb_wstream_file_t *f __attribute__((unused)),
|
||||
void *userdata, const void *buf, size_t len)
|
||||
{
|
||||
ds_stream_ctxt_t *stream_ctxt;
|
||||
|
||||
stream_ctxt = (ds_stream_ctxt_t *) userdata;
|
||||
|
||||
xb_ad(stream_ctxt != NULL);
|
||||
xb_ad(stream_ctxt->dest_file != NULL);
|
||||
|
||||
if (!ds_write(stream_ctxt->dest_file, buf, len)) {
|
||||
return len;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
static
|
||||
ds_ctxt_t *
|
||||
xbstream_init(const char *root __attribute__((unused)))
|
||||
{
|
||||
ds_ctxt_t *ctxt;
|
||||
ds_stream_ctxt_t *stream_ctxt;
|
||||
xb_wstream_t *xbstream;
|
||||
|
||||
ctxt = my_malloc(sizeof(ds_ctxt_t) + sizeof(ds_stream_ctxt_t),
|
||||
MYF(MY_FAE));
|
||||
stream_ctxt = (ds_stream_ctxt_t *)(ctxt + 1);
|
||||
|
||||
if (pthread_mutex_init(&stream_ctxt->mutex, NULL)) {
|
||||
msg("xbstream_init: pthread_mutex_init() failed.\n");
|
||||
goto err;
|
||||
}
|
||||
|
||||
xbstream = xb_stream_write_new();
|
||||
if (xbstream == NULL) {
|
||||
msg("xb_stream_write_new() failed.\n");
|
||||
goto err;
|
||||
}
|
||||
stream_ctxt->xbstream = xbstream;
|
||||
stream_ctxt->dest_file = NULL;
|
||||
|
||||
ctxt->ptr = stream_ctxt;
|
||||
|
||||
return ctxt;
|
||||
|
||||
err:
|
||||
my_free(ctxt);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static
|
||||
ds_file_t *
|
||||
xbstream_open(ds_ctxt_t *ctxt, const char *path, MY_STAT *mystat)
|
||||
{
|
||||
ds_file_t *file;
|
||||
ds_stream_file_t *stream_file;
|
||||
ds_stream_ctxt_t *stream_ctxt;
|
||||
ds_ctxt_t *dest_ctxt;
|
||||
xb_wstream_t *xbstream;
|
||||
xb_wstream_file_t *xbstream_file;
|
||||
|
||||
|
||||
xb_ad(ctxt->pipe_ctxt != NULL);
|
||||
dest_ctxt = ctxt->pipe_ctxt;
|
||||
|
||||
stream_ctxt = (ds_stream_ctxt_t *) ctxt->ptr;
|
||||
|
||||
pthread_mutex_lock(&stream_ctxt->mutex);
|
||||
if (stream_ctxt->dest_file == NULL) {
|
||||
stream_ctxt->dest_file = ds_open(dest_ctxt, path, mystat);
|
||||
if (stream_ctxt->dest_file == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
pthread_mutex_unlock(&stream_ctxt->mutex);
|
||||
|
||||
file = (ds_file_t *) my_malloc(sizeof(ds_file_t) +
|
||||
sizeof(ds_stream_file_t),
|
||||
MYF(MY_FAE));
|
||||
stream_file = (ds_stream_file_t *) (file + 1);
|
||||
|
||||
xbstream = stream_ctxt->xbstream;
|
||||
|
||||
xbstream_file = xb_stream_write_open(xbstream, path, mystat,
|
||||
stream_ctxt,
|
||||
my_xbstream_write_callback);
|
||||
|
||||
if (xbstream_file == NULL) {
|
||||
msg("xb_stream_write_open() failed.\n");
|
||||
goto err;
|
||||
}
|
||||
|
||||
stream_file->xbstream_file = xbstream_file;
|
||||
stream_file->stream_ctxt = stream_ctxt;
|
||||
file->ptr = stream_file;
|
||||
file->path = stream_ctxt->dest_file->path;
|
||||
|
||||
return file;
|
||||
|
||||
err:
|
||||
if (stream_ctxt->dest_file) {
|
||||
ds_close(stream_ctxt->dest_file);
|
||||
stream_ctxt->dest_file = NULL;
|
||||
}
|
||||
my_free(file);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static
|
||||
int
|
||||
xbstream_write(ds_file_t *file, const void *buf, size_t len)
|
||||
{
|
||||
ds_stream_file_t *stream_file;
|
||||
xb_wstream_file_t *xbstream_file;
|
||||
|
||||
|
||||
stream_file = (ds_stream_file_t *) file->ptr;
|
||||
|
||||
xbstream_file = stream_file->xbstream_file;
|
||||
|
||||
if (xb_stream_write_data(xbstream_file, buf, len)) {
|
||||
msg("xb_stream_write_data() failed.\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static
|
||||
int
|
||||
xbstream_close(ds_file_t *file)
|
||||
{
|
||||
ds_stream_file_t *stream_file;
|
||||
int rc = 0;
|
||||
|
||||
stream_file = (ds_stream_file_t *)file->ptr;
|
||||
|
||||
rc = xb_stream_write_close(stream_file->xbstream_file);
|
||||
|
||||
my_free(file);
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
static
|
||||
void
|
||||
xbstream_deinit(ds_ctxt_t *ctxt)
|
||||
{
|
||||
ds_stream_ctxt_t *stream_ctxt;
|
||||
|
||||
stream_ctxt = (ds_stream_ctxt_t *) ctxt->ptr;
|
||||
|
||||
if (xb_stream_write_done(stream_ctxt->xbstream)) {
|
||||
msg("xb_stream_done() failed.\n");
|
||||
}
|
||||
|
||||
if (stream_ctxt->dest_file) {
|
||||
ds_close(stream_ctxt->dest_file);
|
||||
stream_ctxt->dest_file = NULL;
|
||||
}
|
||||
|
||||
pthread_mutex_destroy(&stream_ctxt->mutex);
|
||||
|
||||
my_free(ctxt);
|
||||
}
|
28
extra/mariabackup/ds_xbstream.h
Normal file
28
extra/mariabackup/ds_xbstream.h
Normal file
|
@ -0,0 +1,28 @@
|
|||
/******************************************************
|
||||
Copyright (c) 2011-2013 Percona LLC and/or its affiliates.
|
||||
|
||||
Streaming interface for XtraBackup.
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; version 2 of the License.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
|
||||
|
||||
*******************************************************/
|
||||
|
||||
#ifndef DS_XBSTREAM_H
|
||||
#define DS_XBSTREAM_H
|
||||
|
||||
#include "datasink.h"
|
||||
|
||||
extern datasink_t datasink_xbstream;
|
||||
|
||||
#endif
|
157
extra/mariabackup/encryption_plugin.cc
Normal file
157
extra/mariabackup/encryption_plugin.cc
Normal file
|
@ -0,0 +1,157 @@
|
|||
#include <mysqld.h>
|
||||
#include <mysql.h>
|
||||
#include <xtrabackup.h>
|
||||
#include <encryption_plugin.h>
|
||||
#include <backup_copy.h>
|
||||
#include <sql_plugin.h>
|
||||
#include <sstream>
|
||||
#include <vector>
|
||||
#include <common.h>
|
||||
#include <backup_mysql.h>
|
||||
|
||||
|
||||
extern struct st_maria_plugin *mysql_optional_plugins[];
|
||||
extern struct st_maria_plugin *mysql_mandatory_plugins[];
|
||||
static void encryption_plugin_init(int argc, char **argv);
|
||||
|
||||
extern char *xb_plugin_load;
|
||||
extern char *xb_plugin_dir;
|
||||
|
||||
const int PLUGIN_MAX_ARGS = 1024;
|
||||
vector<string> backup_plugins_args;
|
||||
|
||||
const char *QUERY_PLUGIN =
|
||||
"SELECT plugin_name, plugin_library, @@plugin_dir"
|
||||
" FROM information_schema.plugins WHERE plugin_type='ENCRYPTION'"
|
||||
" AND plugin_status='ACTIVE'";
|
||||
|
||||
string encryption_plugin_config;
|
||||
|
||||
static void add_to_plugin_load_list(const char *plugin_def)
|
||||
{
|
||||
opt_plugin_load_list_ptr->push_back(new i_string(plugin_def));
|
||||
}
|
||||
|
||||
static char XTRABACKUP_EXE[] = "xtrabackup";
|
||||
|
||||
void encryption_plugin_backup_init(MYSQL *mysql)
|
||||
{
|
||||
MYSQL_RES *result;
|
||||
MYSQL_ROW row;
|
||||
ostringstream oss;
|
||||
char *argv[PLUGIN_MAX_ARGS];
|
||||
int argc;
|
||||
|
||||
result = xb_mysql_query(mysql, QUERY_PLUGIN, true, true);
|
||||
row = mysql_fetch_row(result);
|
||||
if (!row)
|
||||
{
|
||||
mysql_free_result(result);
|
||||
return;
|
||||
}
|
||||
|
||||
char *name= row[0];
|
||||
char *library= row[1];
|
||||
char *dir= row[2];
|
||||
|
||||
#ifdef _WIN32
|
||||
for (char *p = dir; *p; p++)
|
||||
if (*p == '\\') *p = '/';
|
||||
#endif
|
||||
|
||||
string plugin_load(name);
|
||||
if (library)
|
||||
plugin_load += string("=") + library;
|
||||
|
||||
oss << "plugin_load=" << plugin_load << endl;
|
||||
|
||||
/* Required to load the plugin later.*/
|
||||
add_to_plugin_load_list(plugin_load.c_str());
|
||||
strncpy(opt_plugin_dir, dir, FN_REFLEN);
|
||||
|
||||
oss << "plugin_dir=" << '"' << dir << '"' << endl;
|
||||
|
||||
|
||||
/* Read plugin variables. */
|
||||
char query[1024];
|
||||
snprintf(query, 1024, "SHOW variables like '%s_%%'", name);
|
||||
mysql_free_result(result);
|
||||
|
||||
result = xb_mysql_query(mysql, query, true, true);
|
||||
while ((row = mysql_fetch_row(result)))
|
||||
{
|
||||
string arg("--");
|
||||
arg += row[0];
|
||||
arg += "=";
|
||||
arg += row[1];
|
||||
backup_plugins_args.push_back(arg);
|
||||
oss << row[0] << "=" << row[1] << endl;
|
||||
}
|
||||
|
||||
mysql_free_result(result);
|
||||
|
||||
/* Check whether to encrypt logs. */
|
||||
result = xb_mysql_query(mysql, "select @@innodb_encrypt_log", true, true);
|
||||
row = mysql_fetch_row(result);
|
||||
srv_encrypt_log = (row != 0 && row[0][0] == '1');
|
||||
oss << "innodb_encrypt_log=" << row[0] << endl;
|
||||
|
||||
mysql_free_result(result);
|
||||
|
||||
encryption_plugin_config = oss.str();
|
||||
|
||||
argc = 0;
|
||||
argv[argc++] = XTRABACKUP_EXE;
|
||||
for(size_t i = 0; i < backup_plugins_args.size(); i++)
|
||||
{
|
||||
argv[argc++] = (char *)backup_plugins_args[i].c_str();
|
||||
if (argc == PLUGIN_MAX_ARGS - 2)
|
||||
break;
|
||||
}
|
||||
argv[argc] = 0;
|
||||
|
||||
encryption_plugin_init(argc, argv);
|
||||
}
|
||||
|
||||
const char *encryption_plugin_get_config()
|
||||
{
|
||||
return encryption_plugin_config.c_str();
|
||||
}
|
||||
|
||||
extern int finalize_encryption_plugin(st_plugin_int *plugin);
|
||||
|
||||
|
||||
void encryption_plugin_prepare_init(int argc, char **argv)
|
||||
{
|
||||
|
||||
if (!xb_plugin_load)
|
||||
{
|
||||
/* This prevents crashes e.g in --stats with wrong my.cnf*/
|
||||
finalize_encryption_plugin(0);
|
||||
return;
|
||||
}
|
||||
|
||||
add_to_plugin_load_list(xb_plugin_load);
|
||||
|
||||
if (xb_plugin_dir)
|
||||
strncpy(opt_plugin_dir, xb_plugin_dir, FN_REFLEN);
|
||||
|
||||
char **new_argv = new char *[argc + 1];
|
||||
new_argv[0] = XTRABACKUP_EXE;
|
||||
memcpy(&new_argv[1], argv, argc*sizeof(char *));
|
||||
|
||||
encryption_plugin_init(argc+1, new_argv);
|
||||
|
||||
delete[] new_argv;
|
||||
}
|
||||
|
||||
static void encryption_plugin_init(int argc, char **argv)
|
||||
{
|
||||
/* Patch optional and mandatory plugins, we only need to load the one in xb_plugin_load. */
|
||||
mysql_optional_plugins[0] = mysql_mandatory_plugins[0] = 0;
|
||||
msg("Loading encryption plugin\n");
|
||||
for (int i= 1; i < argc; i++)
|
||||
msg("\t Encryption plugin parameter : '%s'\n", argv[i]);
|
||||
plugin_init(&argc, argv, PLUGIN_INIT_SKIP_PLUGIN_TABLE);
|
||||
}
|
||||
|
7
extra/mariabackup/encryption_plugin.h
Normal file
7
extra/mariabackup/encryption_plugin.h
Normal file
|
@ -0,0 +1,7 @@
|
|||
#include <mysql.h>
|
||||
#include <string>
|
||||
extern void encryption_plugin_backup_init(MYSQL *mysql);
|
||||
extern const char* encryption_plugin_get_config();
|
||||
extern void encryption_plugin_prepare_init(int argc, char **argv);
|
||||
|
||||
//extern void encryption_plugin_init(int argc, char **argv);
|
409
extra/mariabackup/fil_cur.cc
Normal file
409
extra/mariabackup/fil_cur.cc
Normal file
|
@ -0,0 +1,409 @@
|
|||
/******************************************************
|
||||
XtraBackup: hot backup tool for InnoDB
|
||||
(c) 2009-2013 Percona LLC and/or its affiliates.
|
||||
Originally Created 3/3/2009 Yasufumi Kinoshita
|
||||
Written by Alexey Kopytov, Aleksandr Kuzminsky, Stewart Smith, Vadim Tkachenko,
|
||||
Yasufumi Kinoshita, Ignacio Nin and Baron Schwartz.
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; version 2 of the License.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
|
||||
|
||||
*******************************************************/
|
||||
|
||||
/* Source file cursor implementation */
|
||||
|
||||
#include <my_base.h>
|
||||
|
||||
#include <univ.i>
|
||||
#include <fil0fil.h>
|
||||
#include <srv0start.h>
|
||||
#include <trx0sys.h>
|
||||
|
||||
#include "fil_cur.h"
|
||||
#include "common.h"
|
||||
#include "read_filt.h"
|
||||
#include "xtrabackup.h"
|
||||
#include "xb0xb.h"
|
||||
|
||||
/* Size of read buffer in pages (640 pages = 10M for 16K sized pages) */
|
||||
#define XB_FIL_CUR_PAGES 640
|
||||
|
||||
/***********************************************************************
|
||||
Extracts the relative path ("database/table.ibd") of a tablespace from a
|
||||
specified possibly absolute path.
|
||||
|
||||
For user tablespaces both "./database/table.ibd" and
|
||||
"/remote/dir/database/table.ibd" result in "database/table.ibd".
|
||||
|
||||
For system tablepsaces (i.e. When is_system is TRUE) both "/remote/dir/ibdata1"
|
||||
and "./ibdata1" yield "ibdata1" in the output. */
|
||||
const char *
|
||||
xb_get_relative_path(
|
||||
/*=================*/
|
||||
const char* path, /*!< in: tablespace path (either
|
||||
relative or absolute) */
|
||||
ibool is_system) /*!< in: TRUE for system tablespaces,
|
||||
i.e. when only the filename must be
|
||||
returned. */
|
||||
{
|
||||
const char *next;
|
||||
const char *cur;
|
||||
const char *prev;
|
||||
|
||||
prev = NULL;
|
||||
cur = path;
|
||||
|
||||
while ((next = strchr(cur, SRV_PATH_SEPARATOR)) != NULL) {
|
||||
|
||||
prev = cur;
|
||||
cur = next + 1;
|
||||
}
|
||||
|
||||
if (is_system) {
|
||||
|
||||
return(cur);
|
||||
} else {
|
||||
|
||||
return((prev == NULL) ? cur : prev);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**********************************************************************//**
|
||||
Closes a file. */
|
||||
static
|
||||
void
|
||||
xb_fil_node_close_file(
|
||||
/*===================*/
|
||||
fil_node_t* node) /*!< in: file node */
|
||||
{
|
||||
ibool ret;
|
||||
|
||||
mutex_enter(&fil_system->mutex);
|
||||
|
||||
ut_ad(node);
|
||||
ut_a(node->n_pending == 0);
|
||||
ut_a(node->n_pending_flushes == 0);
|
||||
ut_a(!node->being_extended);
|
||||
|
||||
if (!node->open) {
|
||||
|
||||
mutex_exit(&fil_system->mutex);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
ret = os_file_close(node->handle);
|
||||
ut_a(ret);
|
||||
|
||||
node->open = FALSE;
|
||||
|
||||
ut_a(fil_system->n_open > 0);
|
||||
fil_system->n_open--;
|
||||
fil_n_file_opened--;
|
||||
|
||||
if (node->space->purpose == FIL_TABLESPACE &&
|
||||
fil_is_user_tablespace_id(node->space->id)) {
|
||||
|
||||
ut_a(UT_LIST_GET_LEN(fil_system->LRU) > 0);
|
||||
|
||||
/* The node is in the LRU list, remove it */
|
||||
UT_LIST_REMOVE(LRU, fil_system->LRU, node);
|
||||
}
|
||||
|
||||
mutex_exit(&fil_system->mutex);
|
||||
}
|
||||
|
||||
/************************************************************************
|
||||
Open a source file cursor and initialize the associated read filter.
|
||||
|
||||
@return XB_FIL_CUR_SUCCESS on success, XB_FIL_CUR_SKIP if the source file must
|
||||
be skipped and XB_FIL_CUR_ERROR on error. */
|
||||
xb_fil_cur_result_t
|
||||
xb_fil_cur_open(
|
||||
/*============*/
|
||||
xb_fil_cur_t* cursor, /*!< out: source file cursor */
|
||||
xb_read_filt_t* read_filter, /*!< in/out: the read filter */
|
||||
fil_node_t* node, /*!< in: source tablespace node */
|
||||
uint thread_n) /*!< thread number for diagnostics */
|
||||
{
|
||||
ulint page_size;
|
||||
ulint page_size_shift;
|
||||
ulint zip_size;
|
||||
ibool success;
|
||||
|
||||
/* Initialize these first so xb_fil_cur_close() handles them correctly
|
||||
in case of error */
|
||||
cursor->orig_buf = NULL;
|
||||
cursor->node = NULL;
|
||||
|
||||
cursor->space_id = node->space->id;
|
||||
cursor->is_system = !fil_is_user_tablespace_id(node->space->id);
|
||||
|
||||
strncpy(cursor->abs_path, node->name, sizeof(cursor->abs_path));
|
||||
|
||||
/* Get the relative path for the destination tablespace name, i.e. the
|
||||
one that can be appended to the backup root directory. Non-system
|
||||
tablespaces may have absolute paths for remote tablespaces in MySQL
|
||||
5.6+. We want to make "local" copies for the backup. */
|
||||
strncpy(cursor->rel_path,
|
||||
xb_get_relative_path(cursor->abs_path, cursor->is_system),
|
||||
sizeof(cursor->rel_path));
|
||||
|
||||
/* In the backup mode we should already have a tablespace handle created
|
||||
by fil_load_single_table_tablespace() unless it is a system
|
||||
tablespace. Otherwise we open the file here. */
|
||||
if (cursor->is_system || !srv_backup_mode || srv_close_files) {
|
||||
node->handle =
|
||||
os_file_create_simple_no_error_handling(0, node->name,
|
||||
OS_FILE_OPEN,
|
||||
OS_FILE_READ_ONLY,
|
||||
&success,0);
|
||||
if (!success) {
|
||||
/* The following call prints an error message */
|
||||
os_file_get_last_error(TRUE);
|
||||
|
||||
msg("[%02u] xtrabackup: error: cannot open "
|
||||
"tablespace %s\n",
|
||||
thread_n, cursor->abs_path);
|
||||
|
||||
return(XB_FIL_CUR_ERROR);
|
||||
}
|
||||
mutex_enter(&fil_system->mutex);
|
||||
|
||||
node->open = TRUE;
|
||||
|
||||
fil_system->n_open++;
|
||||
fil_n_file_opened++;
|
||||
|
||||
if (node->space->purpose == FIL_TABLESPACE &&
|
||||
fil_is_user_tablespace_id(node->space->id)) {
|
||||
|
||||
/* Put the node to the LRU list */
|
||||
UT_LIST_ADD_FIRST(LRU, fil_system->LRU, node);
|
||||
}
|
||||
|
||||
mutex_exit(&fil_system->mutex);
|
||||
}
|
||||
|
||||
ut_ad(node->open);
|
||||
|
||||
cursor->node = node;
|
||||
cursor->file = node->handle;
|
||||
|
||||
if (stat(cursor->abs_path, &cursor->statinfo)) {
|
||||
msg("[%02u] xtrabackup: error: cannot stat %s\n",
|
||||
thread_n, cursor->abs_path);
|
||||
|
||||
xb_fil_cur_close(cursor);
|
||||
|
||||
return(XB_FIL_CUR_ERROR);
|
||||
}
|
||||
|
||||
if (srv_unix_file_flush_method == SRV_UNIX_O_DIRECT
|
||||
|| srv_unix_file_flush_method == SRV_UNIX_O_DIRECT_NO_FSYNC) {
|
||||
|
||||
os_file_set_nocache(cursor->file, node->name, "OPEN");
|
||||
}
|
||||
|
||||
posix_fadvise(cursor->file, 0, 0, POSIX_FADV_SEQUENTIAL);
|
||||
|
||||
/* Determine the page size */
|
||||
zip_size = xb_get_zip_size(cursor->file);
|
||||
if (zip_size == ULINT_UNDEFINED) {
|
||||
xb_fil_cur_close(cursor);
|
||||
return(XB_FIL_CUR_SKIP);
|
||||
} else if (zip_size) {
|
||||
page_size = zip_size;
|
||||
page_size_shift = get_bit_shift(page_size);
|
||||
msg("[%02u] %s is compressed with page size = "
|
||||
"%lu bytes\n", thread_n, node->name, page_size);
|
||||
if (page_size_shift < 10 || page_size_shift > 14) {
|
||||
msg("[%02u] xtrabackup: Error: Invalid "
|
||||
"page size: %lu.\n", thread_n, page_size);
|
||||
ut_error;
|
||||
}
|
||||
} else {
|
||||
page_size = UNIV_PAGE_SIZE;
|
||||
page_size_shift = UNIV_PAGE_SIZE_SHIFT;
|
||||
}
|
||||
cursor->page_size = page_size;
|
||||
cursor->page_size_shift = page_size_shift;
|
||||
cursor->zip_size = zip_size;
|
||||
|
||||
/* Allocate read buffer */
|
||||
cursor->buf_size = XB_FIL_CUR_PAGES * page_size;
|
||||
cursor->orig_buf = static_cast<byte *>
|
||||
(ut_malloc(cursor->buf_size + UNIV_PAGE_SIZE));
|
||||
cursor->buf = static_cast<byte *>
|
||||
(ut_align(cursor->orig_buf, UNIV_PAGE_SIZE));
|
||||
|
||||
cursor->buf_read = 0;
|
||||
cursor->buf_npages = 0;
|
||||
cursor->buf_offset = 0;
|
||||
cursor->buf_page_no = 0;
|
||||
cursor->thread_n = thread_n;
|
||||
|
||||
cursor->space_size = (ulint)(cursor->statinfo.st_size / page_size);
|
||||
|
||||
cursor->read_filter = read_filter;
|
||||
cursor->read_filter->init(&cursor->read_filter_ctxt, cursor,
|
||||
node->space->id);
|
||||
|
||||
return(XB_FIL_CUR_SUCCESS);
|
||||
}
|
||||
|
||||
/************************************************************************
|
||||
Reads and verifies the next block of pages from the source
|
||||
file. Positions the cursor after the last read non-corrupted page.
|
||||
|
||||
@return XB_FIL_CUR_SUCCESS if some have been read successfully, XB_FIL_CUR_EOF
|
||||
if there are no more pages to read and XB_FIL_CUR_ERROR on error. */
|
||||
xb_fil_cur_result_t
|
||||
xb_fil_cur_read(
|
||||
/*============*/
|
||||
xb_fil_cur_t* cursor) /*!< in/out: source file cursor */
|
||||
{
|
||||
ibool success;
|
||||
byte* page;
|
||||
ulint i;
|
||||
ulint npages;
|
||||
ulint retry_count;
|
||||
xb_fil_cur_result_t ret;
|
||||
ib_int64_t offset;
|
||||
ib_int64_t to_read;
|
||||
|
||||
cursor->read_filter->get_next_batch(&cursor->read_filter_ctxt,
|
||||
&offset, &to_read);
|
||||
|
||||
if (to_read == 0LL) {
|
||||
return(XB_FIL_CUR_EOF);
|
||||
}
|
||||
|
||||
if (to_read > (ib_int64_t) cursor->buf_size) {
|
||||
to_read = (ib_int64_t) cursor->buf_size;
|
||||
}
|
||||
|
||||
xb_a(to_read > 0 && to_read <= 0xFFFFFFFFLL);
|
||||
|
||||
if (to_read % cursor->page_size != 0 &&
|
||||
offset + to_read == cursor->statinfo.st_size) {
|
||||
|
||||
if (to_read < (ib_int64_t) cursor->page_size) {
|
||||
msg("[%02u] xtrabackup: Warning: junk at the end of "
|
||||
"%s:\n", cursor->thread_n, cursor->abs_path);
|
||||
msg("[%02u] xtrabackup: Warning: offset = %llu, "
|
||||
"to_read = %llu\n",
|
||||
cursor->thread_n,
|
||||
(unsigned long long) offset,
|
||||
(unsigned long long) to_read);
|
||||
|
||||
return(XB_FIL_CUR_EOF);
|
||||
}
|
||||
|
||||
to_read = (ib_int64_t) (((ulint) to_read) &
|
||||
~(cursor->page_size - 1));
|
||||
}
|
||||
|
||||
xb_a(to_read % cursor->page_size == 0);
|
||||
|
||||
npages = (ulint) (to_read >> cursor->page_size_shift);
|
||||
|
||||
retry_count = 10;
|
||||
ret = XB_FIL_CUR_SUCCESS;
|
||||
|
||||
read_retry:
|
||||
xtrabackup_io_throttling();
|
||||
|
||||
cursor->buf_read = 0;
|
||||
cursor->buf_npages = 0;
|
||||
cursor->buf_offset = offset;
|
||||
cursor->buf_page_no = (ulint)(offset >> cursor->page_size_shift);
|
||||
|
||||
success = os_file_read(cursor->file, cursor->buf, offset,
|
||||
(ulint)to_read);
|
||||
if (!success) {
|
||||
return(XB_FIL_CUR_ERROR);
|
||||
}
|
||||
|
||||
fil_system_enter();
|
||||
fil_space_t *space = fil_space_get_by_id(cursor->space_id);
|
||||
fil_system_exit();
|
||||
|
||||
/* check pages for corruption and re-read if necessary. i.e. in case of
|
||||
partially written pages */
|
||||
for (page = cursor->buf, i = 0; i < npages;
|
||||
page += cursor->page_size, i++) {
|
||||
ib_int64_t page_no = cursor->buf_page_no + i;
|
||||
|
||||
bool checksum_ok = fil_space_verify_crypt_checksum(page, cursor->zip_size,space, (ulint)page_no);
|
||||
|
||||
if (!checksum_ok &&
|
||||
buf_page_is_corrupted(true, page, cursor->zip_size,space)) {
|
||||
|
||||
if (cursor->is_system &&
|
||||
page_no >= (ib_int64_t)FSP_EXTENT_SIZE &&
|
||||
page_no < (ib_int64_t) FSP_EXTENT_SIZE * 3) {
|
||||
/* skip doublewrite buffer pages */
|
||||
xb_a(cursor->page_size == UNIV_PAGE_SIZE);
|
||||
msg("[%02u] xtrabackup: "
|
||||
"Page %lu is a doublewrite buffer page, "
|
||||
"skipping.\n", cursor->thread_n, page_no);
|
||||
} else {
|
||||
retry_count--;
|
||||
if (retry_count == 0) {
|
||||
msg("[%02u] xtrabackup: "
|
||||
"Error: failed to read page after "
|
||||
"10 retries. File %s seems to be "
|
||||
"corrupted.\n", cursor->thread_n,
|
||||
cursor->abs_path);
|
||||
ret = XB_FIL_CUR_ERROR;
|
||||
break;
|
||||
}
|
||||
msg("[%02u] xtrabackup: "
|
||||
"Database page corruption detected at page "
|
||||
"%lu, retrying...\n", cursor->thread_n,
|
||||
page_no);
|
||||
|
||||
os_thread_sleep(100000);
|
||||
|
||||
goto read_retry;
|
||||
}
|
||||
}
|
||||
cursor->buf_read += cursor->page_size;
|
||||
cursor->buf_npages++;
|
||||
}
|
||||
|
||||
posix_fadvise(cursor->file, offset, to_read, POSIX_FADV_DONTNEED);
|
||||
|
||||
return(ret);
|
||||
}
|
||||
|
||||
/************************************************************************
|
||||
Close the source file cursor opened with xb_fil_cur_open() and its
|
||||
associated read filter. */
|
||||
void
|
||||
xb_fil_cur_close(
|
||||
/*=============*/
|
||||
xb_fil_cur_t *cursor) /*!< in/out: source file cursor */
|
||||
{
|
||||
cursor->read_filter->deinit(&cursor->read_filter_ctxt);
|
||||
|
||||
if (cursor->orig_buf != NULL) {
|
||||
ut_free(cursor->orig_buf);
|
||||
}
|
||||
if (cursor->node != NULL) {
|
||||
xb_fil_node_close_file(cursor->node);
|
||||
cursor->file = XB_FILE_UNDEFINED;
|
||||
}
|
||||
}
|
123
extra/mariabackup/fil_cur.h
Normal file
123
extra/mariabackup/fil_cur.h
Normal file
|
@ -0,0 +1,123 @@
|
|||
/******************************************************
|
||||
XtraBackup: hot backup tool for InnoDB
|
||||
(c) 2009-2013 Percona LLC and/or its affiliates.
|
||||
Originally Created 3/3/2009 Yasufumi Kinoshita
|
||||
Written by Alexey Kopytov, Aleksandr Kuzminsky, Stewart Smith, Vadim Tkachenko,
|
||||
Yasufumi Kinoshita, Ignacio Nin and Baron Schwartz.
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; version 2 of the License.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
|
||||
|
||||
*******************************************************/
|
||||
|
||||
/* Source file cursor interface */
|
||||
|
||||
#ifndef FIL_CUR_H
|
||||
#define FIL_CUR_H
|
||||
|
||||
#include <my_dir.h>
|
||||
#include "read_filt.h"
|
||||
|
||||
struct xb_fil_cur_t {
|
||||
os_file_t file; /*!< source file handle */
|
||||
fil_node_t* node; /*!< source tablespace node */
|
||||
char rel_path[FN_REFLEN];
|
||||
/*!< normalized file path */
|
||||
char abs_path[FN_REFLEN];
|
||||
/*!< absolute file path */
|
||||
MY_STAT statinfo; /*!< information about the file */
|
||||
ulint zip_size; /*!< compressed page size in bytes or 0
|
||||
for uncompressed pages */
|
||||
ulint page_size; /*!< = zip_size for compressed pages or
|
||||
UNIV_PAGE_SIZE for uncompressed ones */
|
||||
ulint page_size_shift;/*!< bit shift corresponding to
|
||||
page_size */
|
||||
my_bool is_system; /*!< TRUE for system tablespace, FALSE
|
||||
otherwise */
|
||||
xb_read_filt_t* read_filter; /*!< read filter */
|
||||
xb_read_filt_ctxt_t read_filter_ctxt;
|
||||
/*!< read filter context */
|
||||
byte* orig_buf; /*!< read buffer */
|
||||
byte* buf; /*!< aligned pointer for orig_buf */
|
||||
size_t buf_size; /*!< buffer size in bytes */
|
||||
size_t buf_read; /*!< number of read bytes in buffer
|
||||
after the last cursor read */
|
||||
size_t buf_npages; /*!< number of pages in buffer after the
|
||||
last cursor read */
|
||||
ib_int64_t buf_offset; /*!< file offset of the first page in
|
||||
buffer */
|
||||
ulint buf_page_no; /*!< number of the first page in
|
||||
buffer */
|
||||
uint thread_n; /*!< thread number for diagnostics */
|
||||
ulint space_id; /*!< ID of tablespace */
|
||||
ulint space_size; /*!< space size in pages */
|
||||
};
|
||||
|
||||
typedef enum {
|
||||
XB_FIL_CUR_SUCCESS,
|
||||
XB_FIL_CUR_SKIP,
|
||||
XB_FIL_CUR_ERROR,
|
||||
XB_FIL_CUR_EOF
|
||||
} xb_fil_cur_result_t;
|
||||
|
||||
/************************************************************************
|
||||
Open a source file cursor and initialize the associated read filter.
|
||||
|
||||
@return XB_FIL_CUR_SUCCESS on success, XB_FIL_CUR_SKIP if the source file must
|
||||
be skipped and XB_FIL_CUR_ERROR on error. */
|
||||
xb_fil_cur_result_t
|
||||
xb_fil_cur_open(
|
||||
/*============*/
|
||||
xb_fil_cur_t* cursor, /*!< out: source file cursor */
|
||||
xb_read_filt_t* read_filter, /*!< in/out: the read filter */
|
||||
fil_node_t* node, /*!< in: source tablespace node */
|
||||
uint thread_n); /*!< thread number for diagnostics */
|
||||
|
||||
/************************************************************************
|
||||
Reads and verifies the next block of pages from the source
|
||||
file. Positions the cursor after the last read non-corrupted page.
|
||||
|
||||
@return XB_FIL_CUR_SUCCESS if some have been read successfully, XB_FIL_CUR_EOF
|
||||
if there are no more pages to read and XB_FIL_CUR_ERROR on error. */
|
||||
xb_fil_cur_result_t
|
||||
xb_fil_cur_read(
|
||||
/*============*/
|
||||
xb_fil_cur_t* cursor); /*!< in/out: source file cursor */
|
||||
|
||||
/************************************************************************
|
||||
Close the source file cursor opened with xb_fil_cur_open() and its
|
||||
associated read filter. */
|
||||
void
|
||||
xb_fil_cur_close(
|
||||
/*=============*/
|
||||
xb_fil_cur_t *cursor); /*!< in/out: source file cursor */
|
||||
|
||||
/***********************************************************************
|
||||
Extracts the relative path ("database/table.ibd") of a tablespace from a
|
||||
specified possibly absolute path.
|
||||
|
||||
For user tablespaces both "./database/table.ibd" and
|
||||
"/remote/dir/database/table.ibd" result in "database/table.ibd".
|
||||
|
||||
For system tablepsaces (i.e. When is_system is TRUE) both "/remote/dir/ibdata1"
|
||||
and "./ibdata1" yield "ibdata1" in the output. */
|
||||
const char *
|
||||
xb_get_relative_path(
|
||||
/*=================*/
|
||||
const char* path, /*!< in: tablespace path (either
|
||||
relative or absolute) */
|
||||
ibool is_system); /*!< in: TRUE for system tablespaces,
|
||||
i.e. when only the filename must be
|
||||
returned. */
|
||||
|
||||
#endif
|
1132
extra/mariabackup/innobackupex.cc
Normal file
1132
extra/mariabackup/innobackupex.cc
Normal file
File diff suppressed because it is too large
Load diff
45
extra/mariabackup/innobackupex.h
Normal file
45
extra/mariabackup/innobackupex.h
Normal file
|
@ -0,0 +1,45 @@
|
|||
/******************************************************
|
||||
Copyright (c) 2011-2014 Percona LLC and/or its affiliates.
|
||||
|
||||
Declarations for innobackupex.cc
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; version 2 of the License.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
|
||||
|
||||
*******************************************************/
|
||||
|
||||
#ifndef INNOBACKUPEX_H
|
||||
#define INNOBACKUPEX_H
|
||||
|
||||
#define INNOBACKUPEX_BIN_NAME "innobackupex"
|
||||
|
||||
enum ibx_mode_t {
|
||||
IBX_MODE_BACKUP,
|
||||
IBX_MODE_APPLY_LOG,
|
||||
IBX_MODE_COPY_BACK,
|
||||
IBX_MODE_MOVE_BACK,
|
||||
IBX_MODE_DECRYPT_DECOMPRESS
|
||||
};
|
||||
|
||||
extern ibx_mode_t ibx_mode;
|
||||
|
||||
bool
|
||||
ibx_handle_options(int *argc, char ***argv);
|
||||
|
||||
bool
|
||||
ibx_init();
|
||||
|
||||
void
|
||||
ibx_cleanup();
|
||||
|
||||
#endif
|
848
extra/mariabackup/quicklz/quicklz.c
Normal file
848
extra/mariabackup/quicklz/quicklz.c
Normal file
|
@ -0,0 +1,848 @@
|
|||
// Fast data compression library
|
||||
// Copyright (C) 2006-2011 Lasse Mikkel Reinhold
|
||||
// lar@quicklz.com
|
||||
//
|
||||
// QuickLZ can be used for free under the GPL 1, 2 or 3 license (where anything
|
||||
// released into public must be open source) or under a commercial license if such
|
||||
// has been acquired (see http://www.quicklz.com/order.html). The commercial license
|
||||
// does not cover derived or ported versions created by third parties under GPL.
|
||||
|
||||
// 1.5.0 final
|
||||
|
||||
#include "quicklz.h"
|
||||
|
||||
#if QLZ_VERSION_MAJOR != 1 || QLZ_VERSION_MINOR != 5 || QLZ_VERSION_REVISION != 0
|
||||
#error quicklz.c and quicklz.h have different versions
|
||||
#endif
|
||||
|
||||
#if (defined(__X86__) || defined(__i386__) || defined(i386) || defined(_M_IX86) || defined(__386__) || defined(__x86_64__) || defined(_M_X64))
|
||||
#define X86X64
|
||||
#endif
|
||||
|
||||
#define MINOFFSET 2
|
||||
#define UNCONDITIONAL_MATCHLEN 6
|
||||
#define UNCOMPRESSED_END 4
|
||||
#define CWORD_LEN 4
|
||||
|
||||
#if QLZ_COMPRESSION_LEVEL == 1 && defined QLZ_PTR_64 && QLZ_STREAMING_BUFFER == 0
|
||||
#define OFFSET_BASE source
|
||||
#define CAST (ui32)(size_t)
|
||||
#else
|
||||
#define OFFSET_BASE 0
|
||||
#define CAST
|
||||
#endif
|
||||
|
||||
int qlz_get_setting(int setting)
|
||||
{
|
||||
switch (setting)
|
||||
{
|
||||
case 0: return QLZ_COMPRESSION_LEVEL;
|
||||
case 1: return sizeof(qlz_state_compress);
|
||||
case 2: return sizeof(qlz_state_decompress);
|
||||
case 3: return QLZ_STREAMING_BUFFER;
|
||||
#ifdef QLZ_MEMORY_SAFE
|
||||
case 6: return 1;
|
||||
#else
|
||||
case 6: return 0;
|
||||
#endif
|
||||
case 7: return QLZ_VERSION_MAJOR;
|
||||
case 8: return QLZ_VERSION_MINOR;
|
||||
case 9: return QLZ_VERSION_REVISION;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
#if QLZ_COMPRESSION_LEVEL == 1
|
||||
static int same(const unsigned char *src, size_t n)
|
||||
{
|
||||
while(n > 0 && *(src + n) == *src)
|
||||
n--;
|
||||
return n == 0 ? 1 : 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
static void reset_table_compress(qlz_state_compress *state)
|
||||
{
|
||||
int i;
|
||||
for(i = 0; i < QLZ_HASH_VALUES; i++)
|
||||
{
|
||||
#if QLZ_COMPRESSION_LEVEL == 1
|
||||
state->hash[i].offset = 0;
|
||||
#else
|
||||
state->hash_counter[i] = 0;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
static void reset_table_decompress(qlz_state_decompress *state)
|
||||
{
|
||||
int i;
|
||||
(void)state;
|
||||
(void)i;
|
||||
#if QLZ_COMPRESSION_LEVEL == 2
|
||||
for(i = 0; i < QLZ_HASH_VALUES; i++)
|
||||
{
|
||||
state->hash_counter[i] = 0;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
static __inline ui32 hash_func(ui32 i)
|
||||
{
|
||||
#if QLZ_COMPRESSION_LEVEL == 2
|
||||
return ((i >> 9) ^ (i >> 13) ^ i) & (QLZ_HASH_VALUES - 1);
|
||||
#else
|
||||
return ((i >> 12) ^ i) & (QLZ_HASH_VALUES - 1);
|
||||
#endif
|
||||
}
|
||||
|
||||
static __inline ui32 fast_read(void const *src, ui32 bytes)
|
||||
{
|
||||
#ifndef X86X64
|
||||
unsigned char *p = (unsigned char*)src;
|
||||
switch (bytes)
|
||||
{
|
||||
case 4:
|
||||
return(*p | *(p + 1) << 8 | *(p + 2) << 16 | *(p + 3) << 24);
|
||||
case 3:
|
||||
return(*p | *(p + 1) << 8 | *(p + 2) << 16);
|
||||
case 2:
|
||||
return(*p | *(p + 1) << 8);
|
||||
case 1:
|
||||
return(*p);
|
||||
}
|
||||
return 0;
|
||||
#else
|
||||
if (bytes >= 1 && bytes <= 4)
|
||||
return *((ui32*)src);
|
||||
else
|
||||
return 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
static __inline ui32 hashat(const unsigned char *src)
|
||||
{
|
||||
ui32 fetch, hash;
|
||||
fetch = fast_read(src, 3);
|
||||
hash = hash_func(fetch);
|
||||
return hash;
|
||||
}
|
||||
|
||||
static __inline void fast_write(ui32 f, void *dst, size_t bytes)
|
||||
{
|
||||
#ifndef X86X64
|
||||
unsigned char *p = (unsigned char*)dst;
|
||||
|
||||
switch (bytes)
|
||||
{
|
||||
case 4:
|
||||
*p = (unsigned char)f;
|
||||
*(p + 1) = (unsigned char)(f >> 8);
|
||||
*(p + 2) = (unsigned char)(f >> 16);
|
||||
*(p + 3) = (unsigned char)(f >> 24);
|
||||
return;
|
||||
case 3:
|
||||
*p = (unsigned char)f;
|
||||
*(p + 1) = (unsigned char)(f >> 8);
|
||||
*(p + 2) = (unsigned char)(f >> 16);
|
||||
return;
|
||||
case 2:
|
||||
*p = (unsigned char)f;
|
||||
*(p + 1) = (unsigned char)(f >> 8);
|
||||
return;
|
||||
case 1:
|
||||
*p = (unsigned char)f;
|
||||
return;
|
||||
}
|
||||
#else
|
||||
switch (bytes)
|
||||
{
|
||||
case 4:
|
||||
*((ui32*)dst) = f;
|
||||
return;
|
||||
case 3:
|
||||
*((ui32*)dst) = f;
|
||||
return;
|
||||
case 2:
|
||||
*((ui16 *)dst) = (ui16)f;
|
||||
return;
|
||||
case 1:
|
||||
*((unsigned char*)dst) = (unsigned char)f;
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
size_t qlz_size_decompressed(const char *source)
|
||||
{
|
||||
ui32 n, r;
|
||||
n = (((*source) & 2) == 2) ? 4 : 1;
|
||||
r = fast_read(source + 1 + n, n);
|
||||
r = r & (0xffffffff >> ((4 - n)*8));
|
||||
return r;
|
||||
}
|
||||
|
||||
size_t qlz_size_compressed(const char *source)
|
||||
{
|
||||
ui32 n, r;
|
||||
n = (((*source) & 2) == 2) ? 4 : 1;
|
||||
r = fast_read(source + 1, n);
|
||||
r = r & (0xffffffff >> ((4 - n)*8));
|
||||
return r;
|
||||
}
|
||||
|
||||
size_t qlz_size_header(const char *source)
|
||||
{
|
||||
size_t n = 2*((((*source) & 2) == 2) ? 4 : 1) + 1;
|
||||
return n;
|
||||
}
|
||||
|
||||
|
||||
static __inline void memcpy_up(unsigned char *dst, const unsigned char *src, ui32 n)
|
||||
{
|
||||
// Caution if modifying memcpy_up! Overlap of dst and src must be special handled.
|
||||
#ifndef X86X64
|
||||
unsigned char *end = dst + n;
|
||||
while(dst < end)
|
||||
{
|
||||
*dst = *src;
|
||||
dst++;
|
||||
src++;
|
||||
}
|
||||
#else
|
||||
ui32 f = 0;
|
||||
do
|
||||
{
|
||||
*(ui32 *)(dst + f) = *(ui32 *)(src + f);
|
||||
f += MINOFFSET + 1;
|
||||
}
|
||||
while (f < n);
|
||||
#endif
|
||||
}
|
||||
|
||||
static __inline void update_hash(qlz_state_decompress *state, const unsigned char *s)
|
||||
{
|
||||
#if QLZ_COMPRESSION_LEVEL == 1
|
||||
ui32 hash;
|
||||
hash = hashat(s);
|
||||
state->hash[hash].offset = s;
|
||||
state->hash_counter[hash] = 1;
|
||||
#elif QLZ_COMPRESSION_LEVEL == 2
|
||||
ui32 hash;
|
||||
unsigned char c;
|
||||
hash = hashat(s);
|
||||
c = state->hash_counter[hash];
|
||||
state->hash[hash].offset[c & (QLZ_POINTERS - 1)] = s;
|
||||
c++;
|
||||
state->hash_counter[hash] = c;
|
||||
#endif
|
||||
(void)state;
|
||||
(void)s;
|
||||
}
|
||||
|
||||
#if QLZ_COMPRESSION_LEVEL <= 2
|
||||
static void update_hash_upto(qlz_state_decompress *state, unsigned char **lh, const unsigned char *max)
|
||||
{
|
||||
while(*lh < max)
|
||||
{
|
||||
(*lh)++;
|
||||
update_hash(state, *lh);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
static size_t qlz_compress_core(const unsigned char *source, unsigned char *destination, size_t size, qlz_state_compress *state)
|
||||
{
|
||||
const unsigned char *last_byte = source + size - 1;
|
||||
const unsigned char *src = source;
|
||||
unsigned char *cword_ptr = destination;
|
||||
unsigned char *dst = destination + CWORD_LEN;
|
||||
ui32 cword_val = 1U << 31;
|
||||
const unsigned char *last_matchstart = last_byte - UNCONDITIONAL_MATCHLEN - UNCOMPRESSED_END;
|
||||
ui32 fetch = 0;
|
||||
unsigned int lits = 0;
|
||||
|
||||
(void) lits;
|
||||
|
||||
if(src <= last_matchstart)
|
||||
fetch = fast_read(src, 3);
|
||||
|
||||
while(src <= last_matchstart)
|
||||
{
|
||||
if ((cword_val & 1) == 1)
|
||||
{
|
||||
// store uncompressed if compression ratio is too low
|
||||
if (src > source + (size >> 1) && dst - destination > src - source - ((src - source) >> 5))
|
||||
return 0;
|
||||
|
||||
fast_write((cword_val >> 1) | (1U << 31), cword_ptr, CWORD_LEN);
|
||||
|
||||
cword_ptr = dst;
|
||||
dst += CWORD_LEN;
|
||||
cword_val = 1U << 31;
|
||||
fetch = fast_read(src, 3);
|
||||
}
|
||||
#if QLZ_COMPRESSION_LEVEL == 1
|
||||
{
|
||||
const unsigned char *o;
|
||||
ui32 hash, cached;
|
||||
|
||||
hash = hash_func(fetch);
|
||||
cached = fetch ^ state->hash[hash].cache;
|
||||
state->hash[hash].cache = fetch;
|
||||
|
||||
o = state->hash[hash].offset + OFFSET_BASE;
|
||||
state->hash[hash].offset = CAST(src - OFFSET_BASE);
|
||||
|
||||
#ifdef X86X64
|
||||
if ((cached & 0xffffff) == 0 && o != OFFSET_BASE && (src - o > MINOFFSET || (src == o + 1 && lits >= 3 && src > source + 3 && same(src - 3, 6))))
|
||||
{
|
||||
if(cached != 0)
|
||||
{
|
||||
#else
|
||||
if (cached == 0 && o != OFFSET_BASE && (src - o > MINOFFSET || (src == o + 1 && lits >= 3 && src > source + 3 && same(src - 3, 6))))
|
||||
{
|
||||
if (*(o + 3) != *(src + 3))
|
||||
{
|
||||
#endif
|
||||
hash <<= 4;
|
||||
cword_val = (cword_val >> 1) | (1U << 31);
|
||||
fast_write((3 - 2) | hash, dst, 2);
|
||||
src += 3;
|
||||
dst += 2;
|
||||
}
|
||||
else
|
||||
{
|
||||
const unsigned char *old_src = src;
|
||||
size_t matchlen;
|
||||
hash <<= 4;
|
||||
|
||||
cword_val = (cword_val >> 1) | (1U << 31);
|
||||
src += 4;
|
||||
|
||||
if(*(o + (src - old_src)) == *src)
|
||||
{
|
||||
src++;
|
||||
if(*(o + (src - old_src)) == *src)
|
||||
{
|
||||
size_t q = last_byte - UNCOMPRESSED_END - (src - 5) + 1;
|
||||
size_t remaining = q > 255 ? 255 : q;
|
||||
src++;
|
||||
while(*(o + (src - old_src)) == *src && (size_t)(src - old_src) < remaining)
|
||||
src++;
|
||||
}
|
||||
}
|
||||
|
||||
matchlen = src - old_src;
|
||||
if (matchlen < 18)
|
||||
{
|
||||
fast_write((ui32)(matchlen - 2) | hash, dst, 2);
|
||||
dst += 2;
|
||||
}
|
||||
else
|
||||
{
|
||||
fast_write((ui32)(matchlen << 16) | hash, dst, 3);
|
||||
dst += 3;
|
||||
}
|
||||
}
|
||||
fetch = fast_read(src, 3);
|
||||
lits = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
lits++;
|
||||
*dst = *src;
|
||||
src++;
|
||||
dst++;
|
||||
cword_val = (cword_val >> 1);
|
||||
#ifdef X86X64
|
||||
fetch = fast_read(src, 3);
|
||||
#else
|
||||
fetch = (fetch >> 8 & 0xffff) | (*(src + 2) << 16);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
#elif QLZ_COMPRESSION_LEVEL >= 2
|
||||
{
|
||||
const unsigned char *o, *offset2;
|
||||
ui32 hash, matchlen, k, m, best_k = 0;
|
||||
unsigned char c;
|
||||
size_t remaining = (last_byte - UNCOMPRESSED_END - src + 1) > 255 ? 255 : (last_byte - UNCOMPRESSED_END - src + 1);
|
||||
(void)best_k;
|
||||
|
||||
|
||||
//hash = hashat(src);
|
||||
fetch = fast_read(src, 3);
|
||||
hash = hash_func(fetch);
|
||||
|
||||
c = state->hash_counter[hash];
|
||||
|
||||
offset2 = state->hash[hash].offset[0];
|
||||
if(offset2 < src - MINOFFSET && c > 0 && ((fast_read(offset2, 3) ^ fetch) & 0xffffff) == 0)
|
||||
{
|
||||
matchlen = 3;
|
||||
if(*(offset2 + matchlen) == *(src + matchlen))
|
||||
{
|
||||
matchlen = 4;
|
||||
while(*(offset2 + matchlen) == *(src + matchlen) && matchlen < remaining)
|
||||
matchlen++;
|
||||
}
|
||||
}
|
||||
else
|
||||
matchlen = 0;
|
||||
for(k = 1; k < QLZ_POINTERS && c > k; k++)
|
||||
{
|
||||
o = state->hash[hash].offset[k];
|
||||
#if QLZ_COMPRESSION_LEVEL == 3
|
||||
if(((fast_read(o, 3) ^ fetch) & 0xffffff) == 0 && o < src - MINOFFSET)
|
||||
#elif QLZ_COMPRESSION_LEVEL == 2
|
||||
if(*(src + matchlen) == *(o + matchlen) && ((fast_read(o, 3) ^ fetch) & 0xffffff) == 0 && o < src - MINOFFSET)
|
||||
#endif
|
||||
{
|
||||
m = 3;
|
||||
while(*(o + m) == *(src + m) && m < remaining)
|
||||
m++;
|
||||
#if QLZ_COMPRESSION_LEVEL == 3
|
||||
if ((m > matchlen) || (m == matchlen && o > offset2))
|
||||
#elif QLZ_COMPRESSION_LEVEL == 2
|
||||
if (m > matchlen)
|
||||
#endif
|
||||
{
|
||||
offset2 = o;
|
||||
matchlen = m;
|
||||
best_k = k;
|
||||
}
|
||||
}
|
||||
}
|
||||
o = offset2;
|
||||
state->hash[hash].offset[c & (QLZ_POINTERS - 1)] = src;
|
||||
c++;
|
||||
state->hash_counter[hash] = c;
|
||||
|
||||
#if QLZ_COMPRESSION_LEVEL == 3
|
||||
if(matchlen > 2 && src - o < 131071)
|
||||
{
|
||||
ui32 u;
|
||||
size_t offset = src - o;
|
||||
|
||||
for(u = 1; u < matchlen; u++)
|
||||
{
|
||||
hash = hashat(src + u);
|
||||
c = state->hash_counter[hash]++;
|
||||
state->hash[hash].offset[c & (QLZ_POINTERS - 1)] = src + u;
|
||||
}
|
||||
|
||||
cword_val = (cword_val >> 1) | (1U << 31);
|
||||
src += matchlen;
|
||||
|
||||
if(matchlen == 3 && offset <= 63)
|
||||
{
|
||||
*dst = (unsigned char)(offset << 2);
|
||||
dst++;
|
||||
}
|
||||
else if (matchlen == 3 && offset <= 16383)
|
||||
{
|
||||
ui32 f = (ui32)((offset << 2) | 1);
|
||||
fast_write(f, dst, 2);
|
||||
dst += 2;
|
||||
}
|
||||
else if (matchlen <= 18 && offset <= 1023)
|
||||
{
|
||||
ui32 f = ((matchlen - 3) << 2) | ((ui32)offset << 6) | 2;
|
||||
fast_write(f, dst, 2);
|
||||
dst += 2;
|
||||
}
|
||||
|
||||
else if(matchlen <= 33)
|
||||
{
|
||||
ui32 f = ((matchlen - 2) << 2) | ((ui32)offset << 7) | 3;
|
||||
fast_write(f, dst, 3);
|
||||
dst += 3;
|
||||
}
|
||||
else
|
||||
{
|
||||
ui32 f = ((matchlen - 3) << 7) | ((ui32)offset << 15) | 3;
|
||||
fast_write(f, dst, 4);
|
||||
dst += 4;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
*dst = *src;
|
||||
src++;
|
||||
dst++;
|
||||
cword_val = (cword_val >> 1);
|
||||
}
|
||||
#elif QLZ_COMPRESSION_LEVEL == 2
|
||||
|
||||
if(matchlen > 2)
|
||||
{
|
||||
cword_val = (cword_val >> 1) | (1U << 31);
|
||||
src += matchlen;
|
||||
|
||||
if (matchlen < 10)
|
||||
{
|
||||
ui32 f = best_k | ((matchlen - 2) << 2) | (hash << 5);
|
||||
fast_write(f, dst, 2);
|
||||
dst += 2;
|
||||
}
|
||||
else
|
||||
{
|
||||
ui32 f = best_k | (matchlen << 16) | (hash << 5);
|
||||
fast_write(f, dst, 3);
|
||||
dst += 3;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
*dst = *src;
|
||||
src++;
|
||||
dst++;
|
||||
cword_val = (cword_val >> 1);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
}
|
||||
while (src <= last_byte)
|
||||
{
|
||||
if ((cword_val & 1) == 1)
|
||||
{
|
||||
fast_write((cword_val >> 1) | (1U << 31), cword_ptr, CWORD_LEN);
|
||||
cword_ptr = dst;
|
||||
dst += CWORD_LEN;
|
||||
cword_val = 1U << 31;
|
||||
}
|
||||
#if QLZ_COMPRESSION_LEVEL < 3
|
||||
if (src <= last_byte - 3)
|
||||
{
|
||||
#if QLZ_COMPRESSION_LEVEL == 1
|
||||
ui32 hash, fetch;
|
||||
fetch = fast_read(src, 3);
|
||||
hash = hash_func(fetch);
|
||||
state->hash[hash].offset = CAST(src - OFFSET_BASE);
|
||||
state->hash[hash].cache = fetch;
|
||||
#elif QLZ_COMPRESSION_LEVEL == 2
|
||||
ui32 hash;
|
||||
unsigned char c;
|
||||
hash = hashat(src);
|
||||
c = state->hash_counter[hash];
|
||||
state->hash[hash].offset[c & (QLZ_POINTERS - 1)] = src;
|
||||
c++;
|
||||
state->hash_counter[hash] = c;
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
*dst = *src;
|
||||
src++;
|
||||
dst++;
|
||||
cword_val = (cword_val >> 1);
|
||||
}
|
||||
|
||||
while((cword_val & 1) != 1)
|
||||
cword_val = (cword_val >> 1);
|
||||
|
||||
fast_write((cword_val >> 1) | (1U << 31), cword_ptr, CWORD_LEN);
|
||||
|
||||
// min. size must be 9 bytes so that the qlz_size functions can take 9 bytes as argument
|
||||
return dst - destination < 9 ? 9 : dst - destination;
|
||||
}
|
||||
|
||||
static size_t qlz_decompress_core(const unsigned char *source, unsigned char *destination, size_t size, qlz_state_decompress *state, const unsigned char *history)
|
||||
{
|
||||
const unsigned char *src = source + qlz_size_header((const char *)source);
|
||||
unsigned char *dst = destination;
|
||||
const unsigned char *last_destination_byte = destination + size - 1;
|
||||
ui32 cword_val = 1;
|
||||
const unsigned char *last_matchstart = last_destination_byte - UNCONDITIONAL_MATCHLEN - UNCOMPRESSED_END;
|
||||
unsigned char *last_hashed = destination - 1;
|
||||
const unsigned char *last_source_byte = source + qlz_size_compressed((const char *)source) - 1;
|
||||
static const ui32 bitlut[16] = {4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0};
|
||||
|
||||
(void) last_source_byte;
|
||||
(void) last_hashed;
|
||||
(void) state;
|
||||
(void) history;
|
||||
|
||||
for(;;)
|
||||
{
|
||||
ui32 fetch;
|
||||
|
||||
if (cword_val == 1)
|
||||
{
|
||||
#ifdef QLZ_MEMORY_SAFE
|
||||
if(src + CWORD_LEN - 1 > last_source_byte)
|
||||
return 0;
|
||||
#endif
|
||||
cword_val = fast_read(src, CWORD_LEN);
|
||||
src += CWORD_LEN;
|
||||
}
|
||||
|
||||
#ifdef QLZ_MEMORY_SAFE
|
||||
if(src + 4 - 1 > last_source_byte)
|
||||
return 0;
|
||||
#endif
|
||||
|
||||
fetch = fast_read(src, 4);
|
||||
|
||||
if ((cword_val & 1) == 1)
|
||||
{
|
||||
ui32 matchlen;
|
||||
const unsigned char *offset2;
|
||||
|
||||
#if QLZ_COMPRESSION_LEVEL == 1
|
||||
ui32 hash;
|
||||
cword_val = cword_val >> 1;
|
||||
hash = (fetch >> 4) & 0xfff;
|
||||
offset2 = (const unsigned char *)(size_t)state->hash[hash].offset;
|
||||
|
||||
if((fetch & 0xf) != 0)
|
||||
{
|
||||
matchlen = (fetch & 0xf) + 2;
|
||||
src += 2;
|
||||
}
|
||||
else
|
||||
{
|
||||
matchlen = *(src + 2);
|
||||
src += 3;
|
||||
}
|
||||
|
||||
#elif QLZ_COMPRESSION_LEVEL == 2
|
||||
ui32 hash;
|
||||
unsigned char c;
|
||||
cword_val = cword_val >> 1;
|
||||
hash = (fetch >> 5) & 0x7ff;
|
||||
c = (unsigned char)(fetch & 0x3);
|
||||
offset2 = state->hash[hash].offset[c];
|
||||
|
||||
if((fetch & (28)) != 0)
|
||||
{
|
||||
matchlen = ((fetch >> 2) & 0x7) + 2;
|
||||
src += 2;
|
||||
}
|
||||
else
|
||||
{
|
||||
matchlen = *(src + 2);
|
||||
src += 3;
|
||||
}
|
||||
|
||||
#elif QLZ_COMPRESSION_LEVEL == 3
|
||||
ui32 offset;
|
||||
cword_val = cword_val >> 1;
|
||||
if ((fetch & 3) == 0)
|
||||
{
|
||||
offset = (fetch & 0xff) >> 2;
|
||||
matchlen = 3;
|
||||
src++;
|
||||
}
|
||||
else if ((fetch & 2) == 0)
|
||||
{
|
||||
offset = (fetch & 0xffff) >> 2;
|
||||
matchlen = 3;
|
||||
src += 2;
|
||||
}
|
||||
else if ((fetch & 1) == 0)
|
||||
{
|
||||
offset = (fetch & 0xffff) >> 6;
|
||||
matchlen = ((fetch >> 2) & 15) + 3;
|
||||
src += 2;
|
||||
}
|
||||
else if ((fetch & 127) != 3)
|
||||
{
|
||||
offset = (fetch >> 7) & 0x1ffff;
|
||||
matchlen = ((fetch >> 2) & 0x1f) + 2;
|
||||
src += 3;
|
||||
}
|
||||
else
|
||||
{
|
||||
offset = (fetch >> 15);
|
||||
matchlen = ((fetch >> 7) & 255) + 3;
|
||||
src += 4;
|
||||
}
|
||||
|
||||
offset2 = dst - offset;
|
||||
#endif
|
||||
|
||||
#ifdef QLZ_MEMORY_SAFE
|
||||
if(offset2 < history || offset2 > dst - MINOFFSET - 1)
|
||||
return 0;
|
||||
|
||||
if(matchlen > (ui32)(last_destination_byte - dst - UNCOMPRESSED_END + 1))
|
||||
return 0;
|
||||
#endif
|
||||
|
||||
memcpy_up(dst, offset2, matchlen);
|
||||
dst += matchlen;
|
||||
|
||||
#if QLZ_COMPRESSION_LEVEL <= 2
|
||||
update_hash_upto(state, &last_hashed, dst - matchlen);
|
||||
last_hashed = dst - 1;
|
||||
#endif
|
||||
}
|
||||
else
|
||||
{
|
||||
if (dst < last_matchstart)
|
||||
{
|
||||
unsigned int n = bitlut[cword_val & 0xf];
|
||||
#ifdef X86X64
|
||||
*(ui32 *)dst = *(ui32 *)src;
|
||||
#else
|
||||
memcpy_up(dst, src, 4);
|
||||
#endif
|
||||
cword_val = cword_val >> n;
|
||||
dst += n;
|
||||
src += n;
|
||||
#if QLZ_COMPRESSION_LEVEL <= 2
|
||||
update_hash_upto(state, &last_hashed, dst - 3);
|
||||
#endif
|
||||
}
|
||||
else
|
||||
{
|
||||
while(dst <= last_destination_byte)
|
||||
{
|
||||
if (cword_val == 1)
|
||||
{
|
||||
src += CWORD_LEN;
|
||||
cword_val = 1U << 31;
|
||||
}
|
||||
#ifdef QLZ_MEMORY_SAFE
|
||||
if(src >= last_source_byte + 1)
|
||||
return 0;
|
||||
#endif
|
||||
*dst = *src;
|
||||
dst++;
|
||||
src++;
|
||||
cword_val = cword_val >> 1;
|
||||
}
|
||||
|
||||
#if QLZ_COMPRESSION_LEVEL <= 2
|
||||
update_hash_upto(state, &last_hashed, last_destination_byte - 3); // todo, use constant
|
||||
#endif
|
||||
return size;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
size_t qlz_compress(const void *source, char *destination, size_t size, qlz_state_compress *state)
|
||||
{
|
||||
size_t r;
|
||||
ui32 compressed;
|
||||
size_t base;
|
||||
|
||||
if(size == 0 || size > 0xffffffff - 400)
|
||||
return 0;
|
||||
|
||||
if(size < 216)
|
||||
base = 3;
|
||||
else
|
||||
base = 9;
|
||||
|
||||
#if QLZ_STREAMING_BUFFER > 0
|
||||
if (state->stream_counter + size - 1 >= QLZ_STREAMING_BUFFER)
|
||||
#endif
|
||||
{
|
||||
reset_table_compress(state);
|
||||
r = base + qlz_compress_core((const unsigned char *)source, (unsigned char*)destination + base, size, state);
|
||||
#if QLZ_STREAMING_BUFFER > 0
|
||||
reset_table_compress(state);
|
||||
#endif
|
||||
if(r == base)
|
||||
{
|
||||
memcpy(destination + base, source, size);
|
||||
r = size + base;
|
||||
compressed = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
compressed = 1;
|
||||
}
|
||||
state->stream_counter = 0;
|
||||
}
|
||||
#if QLZ_STREAMING_BUFFER > 0
|
||||
else
|
||||
{
|
||||
unsigned char *src = state->stream_buffer + state->stream_counter;
|
||||
|
||||
memcpy(src, source, size);
|
||||
r = base + qlz_compress_core(src, (unsigned char*)destination + base, size, state);
|
||||
|
||||
if(r == base)
|
||||
{
|
||||
memcpy(destination + base, src, size);
|
||||
r = size + base;
|
||||
compressed = 0;
|
||||
reset_table_compress(state);
|
||||
}
|
||||
else
|
||||
{
|
||||
compressed = 1;
|
||||
}
|
||||
state->stream_counter += size;
|
||||
}
|
||||
#endif
|
||||
if(base == 3)
|
||||
{
|
||||
*destination = (unsigned char)(0 | compressed);
|
||||
*(destination + 1) = (unsigned char)r;
|
||||
*(destination + 2) = (unsigned char)size;
|
||||
}
|
||||
else
|
||||
{
|
||||
*destination = (unsigned char)(2 | compressed);
|
||||
fast_write((ui32)r, destination + 1, 4);
|
||||
fast_write((ui32)size, destination + 5, 4);
|
||||
}
|
||||
|
||||
*destination |= (QLZ_COMPRESSION_LEVEL << 2);
|
||||
*destination |= (1 << 6);
|
||||
*destination |= ((QLZ_STREAMING_BUFFER == 0 ? 0 : (QLZ_STREAMING_BUFFER == 100000 ? 1 : (QLZ_STREAMING_BUFFER == 1000000 ? 2 : 3))) << 4);
|
||||
|
||||
// 76543210
|
||||
// 01SSLLHC
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
size_t qlz_decompress(const char *source, void *destination, qlz_state_decompress *state)
|
||||
{
|
||||
size_t dsiz = qlz_size_decompressed(source);
|
||||
|
||||
#if QLZ_STREAMING_BUFFER > 0
|
||||
if (state->stream_counter + qlz_size_decompressed(source) - 1 >= QLZ_STREAMING_BUFFER)
|
||||
#endif
|
||||
{
|
||||
if((*source & 1) == 1)
|
||||
{
|
||||
reset_table_decompress(state);
|
||||
dsiz = qlz_decompress_core((const unsigned char *)source, (unsigned char *)destination, dsiz, state, (const unsigned char *)destination);
|
||||
}
|
||||
else
|
||||
{
|
||||
memcpy(destination, source + qlz_size_header(source), dsiz);
|
||||
}
|
||||
state->stream_counter = 0;
|
||||
reset_table_decompress(state);
|
||||
}
|
||||
#if QLZ_STREAMING_BUFFER > 0
|
||||
else
|
||||
{
|
||||
unsigned char *dst = state->stream_buffer + state->stream_counter;
|
||||
if((*source & 1) == 1)
|
||||
{
|
||||
dsiz = qlz_decompress_core((const unsigned char *)source, dst, dsiz, state, (const unsigned char *)state->stream_buffer);
|
||||
}
|
||||
else
|
||||
{
|
||||
memcpy(dst, source + qlz_size_header(source), dsiz);
|
||||
reset_table_decompress(state);
|
||||
}
|
||||
memcpy(destination, dst, dsiz);
|
||||
state->stream_counter += dsiz;
|
||||
}
|
||||
#endif
|
||||
return dsiz;
|
||||
}
|
||||
|
144
extra/mariabackup/quicklz/quicklz.h
Normal file
144
extra/mariabackup/quicklz/quicklz.h
Normal file
|
@ -0,0 +1,144 @@
|
|||
#ifndef QLZ_HEADER
|
||||
#define QLZ_HEADER
|
||||
|
||||
// Fast data compression library
|
||||
// Copyright (C) 2006-2011 Lasse Mikkel Reinhold
|
||||
// lar@quicklz.com
|
||||
//
|
||||
// QuickLZ can be used for free under the GPL 1, 2 or 3 license (where anything
|
||||
// released into public must be open source) or under a commercial license if such
|
||||
// has been acquired (see http://www.quicklz.com/order.html). The commercial license
|
||||
// does not cover derived or ported versions created by third parties under GPL.
|
||||
|
||||
// You can edit following user settings. Data must be decompressed with the same
|
||||
// setting of QLZ_COMPRESSION_LEVEL and QLZ_STREAMING_BUFFER as it was compressed
|
||||
// (see manual). If QLZ_STREAMING_BUFFER > 0, scratch buffers must be initially
|
||||
// zeroed out (see manual). First #ifndef makes it possible to define settings from
|
||||
// the outside like the compiler command line.
|
||||
|
||||
// 1.5.0 final
|
||||
|
||||
#ifndef QLZ_COMPRESSION_LEVEL
|
||||
#define QLZ_COMPRESSION_LEVEL 1
|
||||
//#define QLZ_COMPRESSION_LEVEL 2
|
||||
//#define QLZ_COMPRESSION_LEVEL 3
|
||||
|
||||
#define QLZ_STREAMING_BUFFER 0
|
||||
//#define QLZ_STREAMING_BUFFER 100000
|
||||
//#define QLZ_STREAMING_BUFFER 1000000
|
||||
|
||||
//#define QLZ_MEMORY_SAFE
|
||||
#endif
|
||||
|
||||
#define QLZ_VERSION_MAJOR 1
|
||||
#define QLZ_VERSION_MINOR 5
|
||||
#define QLZ_VERSION_REVISION 0
|
||||
|
||||
// Using size_t, memset() and memcpy()
|
||||
#include <string.h>
|
||||
|
||||
// Verify compression level
|
||||
#if QLZ_COMPRESSION_LEVEL != 1 && QLZ_COMPRESSION_LEVEL != 2 && QLZ_COMPRESSION_LEVEL != 3
|
||||
#error QLZ_COMPRESSION_LEVEL must be 1, 2 or 3
|
||||
#endif
|
||||
|
||||
typedef unsigned int ui32;
|
||||
typedef unsigned short int ui16;
|
||||
|
||||
// Decrease QLZ_POINTERS for level 3 to increase compression speed. Do not touch any other values!
|
||||
#if QLZ_COMPRESSION_LEVEL == 1
|
||||
#define QLZ_POINTERS 1
|
||||
#define QLZ_HASH_VALUES 4096
|
||||
#elif QLZ_COMPRESSION_LEVEL == 2
|
||||
#define QLZ_POINTERS 4
|
||||
#define QLZ_HASH_VALUES 2048
|
||||
#elif QLZ_COMPRESSION_LEVEL == 3
|
||||
#define QLZ_POINTERS 16
|
||||
#define QLZ_HASH_VALUES 4096
|
||||
#endif
|
||||
|
||||
// Detect if pointer size is 64-bit. It's not fatal if some 64-bit target is not detected because this is only for adding an optional 64-bit optimization.
|
||||
#if defined _LP64 || defined __LP64__ || defined __64BIT__ || _ADDR64 || defined _WIN64 || defined __arch64__ || __WORDSIZE == 64 || (defined __sparc && defined __sparcv9) || defined __x86_64 || defined __amd64 || defined __x86_64__ || defined _M_X64 || defined _M_IA64 || defined __ia64 || defined __IA64__
|
||||
#define QLZ_PTR_64
|
||||
#endif
|
||||
|
||||
// hash entry
|
||||
typedef struct
|
||||
{
|
||||
#if QLZ_COMPRESSION_LEVEL == 1
|
||||
ui32 cache;
|
||||
#if defined QLZ_PTR_64 && QLZ_STREAMING_BUFFER == 0
|
||||
unsigned int offset;
|
||||
#else
|
||||
const unsigned char *offset;
|
||||
#endif
|
||||
#else
|
||||
const unsigned char *offset[QLZ_POINTERS];
|
||||
#endif
|
||||
|
||||
} qlz_hash_compress;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
#if QLZ_COMPRESSION_LEVEL == 1
|
||||
const unsigned char *offset;
|
||||
#else
|
||||
const unsigned char *offset[QLZ_POINTERS];
|
||||
#endif
|
||||
} qlz_hash_decompress;
|
||||
|
||||
|
||||
// states
|
||||
typedef struct
|
||||
{
|
||||
#if QLZ_STREAMING_BUFFER > 0
|
||||
unsigned char stream_buffer[QLZ_STREAMING_BUFFER];
|
||||
#endif
|
||||
size_t stream_counter;
|
||||
qlz_hash_compress hash[QLZ_HASH_VALUES];
|
||||
unsigned char hash_counter[QLZ_HASH_VALUES];
|
||||
} qlz_state_compress;
|
||||
|
||||
|
||||
#if QLZ_COMPRESSION_LEVEL == 1 || QLZ_COMPRESSION_LEVEL == 2
|
||||
typedef struct
|
||||
{
|
||||
#if QLZ_STREAMING_BUFFER > 0
|
||||
unsigned char stream_buffer[QLZ_STREAMING_BUFFER];
|
||||
#endif
|
||||
qlz_hash_decompress hash[QLZ_HASH_VALUES];
|
||||
unsigned char hash_counter[QLZ_HASH_VALUES];
|
||||
size_t stream_counter;
|
||||
} qlz_state_decompress;
|
||||
#elif QLZ_COMPRESSION_LEVEL == 3
|
||||
typedef struct
|
||||
{
|
||||
#if QLZ_STREAMING_BUFFER > 0
|
||||
unsigned char stream_buffer[QLZ_STREAMING_BUFFER];
|
||||
#endif
|
||||
#if QLZ_COMPRESSION_LEVEL <= 2
|
||||
qlz_hash_decompress hash[QLZ_HASH_VALUES];
|
||||
#endif
|
||||
size_t stream_counter;
|
||||
} qlz_state_decompress;
|
||||
#endif
|
||||
|
||||
|
||||
#if defined (__cplusplus)
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
// Public functions of QuickLZ
|
||||
size_t qlz_size_decompressed(const char *source);
|
||||
size_t qlz_size_compressed(const char *source);
|
||||
size_t qlz_compress(const void *source, char *destination, size_t size, qlz_state_compress *state);
|
||||
size_t qlz_decompress(const char *source, void *destination, qlz_state_decompress *state);
|
||||
int qlz_get_setting(int setting);
|
||||
size_t qlz_size_header(const char *source);
|
||||
|
||||
#if defined (__cplusplus)
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
206
extra/mariabackup/read_filt.cc
Normal file
206
extra/mariabackup/read_filt.cc
Normal file
|
@ -0,0 +1,206 @@
|
|||
/******************************************************
|
||||
XtraBackup: hot backup tool for InnoDB
|
||||
(c) 2009-2012 Percona Inc.
|
||||
Originally Created 3/3/2009 Yasufumi Kinoshita
|
||||
Written by Alexey Kopytov, Aleksandr Kuzminsky, Stewart Smith, Vadim Tkachenko,
|
||||
Yasufumi Kinoshita, Ignacio Nin and Baron Schwartz.
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; version 2 of the License.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
|
||||
|
||||
*******************************************************/
|
||||
|
||||
/* Data file read filter implementation */
|
||||
|
||||
#include "read_filt.h"
|
||||
#include "common.h"
|
||||
#include "fil_cur.h"
|
||||
#include "xtrabackup.h"
|
||||
|
||||
/****************************************************************//**
|
||||
Perform read filter context initialization that is common to all read
|
||||
filters. */
|
||||
static
|
||||
void
|
||||
common_init(
|
||||
/*========*/
|
||||
xb_read_filt_ctxt_t* ctxt, /*!<in/out: read filter context */
|
||||
const xb_fil_cur_t* cursor) /*!<in: file cursor */
|
||||
{
|
||||
ctxt->offset = 0;
|
||||
ctxt->data_file_size = cursor->statinfo.st_size;
|
||||
ctxt->buffer_capacity = cursor->buf_size;
|
||||
ctxt->page_size = cursor->page_size;
|
||||
}
|
||||
|
||||
/****************************************************************//**
|
||||
Initialize the pass-through read filter. */
|
||||
static
|
||||
void
|
||||
rf_pass_through_init(
|
||||
/*=================*/
|
||||
xb_read_filt_ctxt_t* ctxt, /*!<in/out: read filter context */
|
||||
const xb_fil_cur_t* cursor, /*!<in: file cursor */
|
||||
ulint space_id __attribute__((unused)))
|
||||
/*!<in: space id we are reading */
|
||||
{
|
||||
common_init(ctxt, cursor);
|
||||
}
|
||||
|
||||
/****************************************************************//**
|
||||
Get the next batch of pages for the pass-through read filter. */
|
||||
static
|
||||
void
|
||||
rf_pass_through_get_next_batch(
|
||||
/*===========================*/
|
||||
xb_read_filt_ctxt_t* ctxt, /*!<in/out: read filter
|
||||
context */
|
||||
ib_int64_t* read_batch_start, /*!<out: starting read
|
||||
offset in bytes for the
|
||||
next batch of pages */
|
||||
ib_int64_t* read_batch_len) /*!<out: length in
|
||||
bytes of the next batch
|
||||
of pages */
|
||||
{
|
||||
*read_batch_start = ctxt->offset;
|
||||
*read_batch_len = ctxt->data_file_size - ctxt->offset;
|
||||
|
||||
if (*read_batch_len > (ib_int64_t)ctxt->buffer_capacity) {
|
||||
*read_batch_len = ctxt->buffer_capacity;
|
||||
}
|
||||
|
||||
ctxt->offset += *read_batch_len;
|
||||
}
|
||||
|
||||
/****************************************************************//**
|
||||
Deinitialize the pass-through read filter. */
|
||||
static
|
||||
void
|
||||
rf_pass_through_deinit(
|
||||
/*===================*/
|
||||
xb_read_filt_ctxt_t* ctxt __attribute__((unused)))
|
||||
/*!<in: read filter context */
|
||||
{
|
||||
}
|
||||
|
||||
/****************************************************************//**
|
||||
Initialize the changed page bitmap-based read filter. Assumes that
|
||||
the bitmap is already set up in changed_page_bitmap. */
|
||||
static
|
||||
void
|
||||
rf_bitmap_init(
|
||||
/*===========*/
|
||||
xb_read_filt_ctxt_t* ctxt, /*!<in/out: read filter
|
||||
context */
|
||||
const xb_fil_cur_t* cursor, /*!<in: read cursor */
|
||||
ulint space_id) /*!<in: space id */
|
||||
{
|
||||
common_init(ctxt, cursor);
|
||||
ctxt->bitmap_range = xb_page_bitmap_range_init(changed_page_bitmap,
|
||||
space_id);
|
||||
ctxt->filter_batch_end = 0;
|
||||
}
|
||||
|
||||
/****************************************************************//**
|
||||
Get the next batch of pages for the bitmap read filter. */
|
||||
static
|
||||
void
|
||||
rf_bitmap_get_next_batch(
|
||||
/*=====================*/
|
||||
xb_read_filt_ctxt_t* ctxt, /*!<in/out: read filter
|
||||
context */
|
||||
ib_int64_t* read_batch_start, /*!<out: starting read
|
||||
offset in bytes for the
|
||||
next batch of pages */
|
||||
ib_int64_t* read_batch_len) /*!<out: length in
|
||||
bytes of the next batch
|
||||
of pages */
|
||||
{
|
||||
ulint start_page_id;
|
||||
|
||||
start_page_id = (ulint)(ctxt->offset / ctxt->page_size);
|
||||
|
||||
xb_a (ctxt->offset % ctxt->page_size == 0);
|
||||
|
||||
if (start_page_id == ctxt->filter_batch_end) {
|
||||
|
||||
/* Used up all the previous bitmap range, get some more */
|
||||
ulint next_page_id;
|
||||
|
||||
/* Find the next changed page using the bitmap */
|
||||
next_page_id = xb_page_bitmap_range_get_next_bit
|
||||
(ctxt->bitmap_range, TRUE);
|
||||
|
||||
if (next_page_id == ULINT_UNDEFINED) {
|
||||
*read_batch_len = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
ctxt->offset = next_page_id * ctxt->page_size;
|
||||
|
||||
/* Find the end of the current changed page block by searching
|
||||
for the next cleared bitmap bit */
|
||||
ctxt->filter_batch_end
|
||||
= xb_page_bitmap_range_get_next_bit(ctxt->bitmap_range,
|
||||
FALSE);
|
||||
xb_a(next_page_id < ctxt->filter_batch_end);
|
||||
}
|
||||
|
||||
*read_batch_start = ctxt->offset;
|
||||
if (ctxt->filter_batch_end == ULINT_UNDEFINED) {
|
||||
/* No more cleared bits in the bitmap, need to copy all the
|
||||
remaining pages. */
|
||||
*read_batch_len = ctxt->data_file_size - ctxt->offset;
|
||||
} else {
|
||||
*read_batch_len = ctxt->filter_batch_end * ctxt->page_size
|
||||
- ctxt->offset;
|
||||
}
|
||||
|
||||
/* If the page block is larger than the buffer capacity, limit it to
|
||||
buffer capacity. The subsequent invocations will continue returning
|
||||
the current block in buffer-sized pieces until ctxt->filter_batch_end
|
||||
is reached, trigerring the next bitmap query. */
|
||||
if (*read_batch_len > (ib_int64_t)ctxt->buffer_capacity) {
|
||||
*read_batch_len = ctxt->buffer_capacity;
|
||||
}
|
||||
|
||||
ctxt->offset += *read_batch_len;
|
||||
xb_a (ctxt->offset % ctxt->page_size == 0);
|
||||
xb_a (*read_batch_start % ctxt->page_size == 0);
|
||||
xb_a (*read_batch_len % ctxt->page_size == 0);
|
||||
}
|
||||
|
||||
/****************************************************************//**
|
||||
Deinitialize the changed page bitmap-based read filter. */
|
||||
static
|
||||
void
|
||||
rf_bitmap_deinit(
|
||||
/*=============*/
|
||||
xb_read_filt_ctxt_t* ctxt) /*!<in/out: read filter context */
|
||||
{
|
||||
xb_page_bitmap_range_deinit(ctxt->bitmap_range);
|
||||
}
|
||||
|
||||
/* The pass-through read filter */
|
||||
xb_read_filt_t rf_pass_through = {
|
||||
&rf_pass_through_init,
|
||||
&rf_pass_through_get_next_batch,
|
||||
&rf_pass_through_deinit
|
||||
};
|
||||
|
||||
/* The changed page bitmap-based read filter */
|
||||
xb_read_filt_t rf_bitmap = {
|
||||
&rf_bitmap_init,
|
||||
&rf_bitmap_get_next_batch,
|
||||
&rf_bitmap_deinit
|
||||
};
|
62
extra/mariabackup/read_filt.h
Normal file
62
extra/mariabackup/read_filt.h
Normal file
|
@ -0,0 +1,62 @@
|
|||
/******************************************************
|
||||
XtraBackup: hot backup tool for InnoDB
|
||||
(c) 2009-2012 Percona Inc.
|
||||
Originally Created 3/3/2009 Yasufumi Kinoshita
|
||||
Written by Alexey Kopytov, Aleksandr Kuzminsky, Stewart Smith, Vadim Tkachenko,
|
||||
Yasufumi Kinoshita, Ignacio Nin and Baron Schwartz.
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; version 2 of the License.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
|
||||
|
||||
*******************************************************/
|
||||
|
||||
/* Data file read filter interface */
|
||||
|
||||
#ifndef XB_READ_FILT_H
|
||||
#define XB_READ_FILT_H
|
||||
|
||||
#include "changed_page_bitmap.h"
|
||||
|
||||
struct xb_fil_cur_t;
|
||||
|
||||
/* The read filter context */
|
||||
struct xb_read_filt_ctxt_t {
|
||||
ib_int64_t offset; /*!< current file offset */
|
||||
ib_int64_t data_file_size; /*!< data file size */
|
||||
size_t buffer_capacity;/*!< read buffer capacity */
|
||||
ib_int64_t space_id; /*!< space id */
|
||||
/* The following fields used only in bitmap filter */
|
||||
/* Move these to union if any other filters are added in future */
|
||||
xb_page_bitmap_range *bitmap_range; /*!< changed page bitmap range
|
||||
iterator for space_id */
|
||||
size_t page_size; /*!< page size */
|
||||
ulint filter_batch_end;/*!< the ending page id of the
|
||||
current changed page block in
|
||||
the bitmap */
|
||||
};
|
||||
|
||||
/* The read filter */
|
||||
struct xb_read_filt_t {
|
||||
void (*init)(xb_read_filt_ctxt_t* ctxt,
|
||||
const xb_fil_cur_t* cursor,
|
||||
ulint space_id);
|
||||
void (*get_next_batch)(xb_read_filt_ctxt_t* ctxt,
|
||||
ib_int64_t* read_batch_start,
|
||||
ib_int64_t* read_batch_len);
|
||||
void (*deinit)(xb_read_filt_ctxt_t* ctxt);
|
||||
};
|
||||
|
||||
extern xb_read_filt_t rf_pass_through;
|
||||
extern xb_read_filt_t rf_bitmap;
|
||||
|
||||
#endif
|
219
extra/mariabackup/write_filt.cc
Normal file
219
extra/mariabackup/write_filt.cc
Normal file
|
@ -0,0 +1,219 @@
|
|||
/******************************************************
|
||||
XtraBackup: hot backup tool for InnoDB
|
||||
(c) 2009-2013 Percona LLC and/or its affiliates.
|
||||
Originally Created 3/3/2009 Yasufumi Kinoshita
|
||||
Written by Alexey Kopytov, Aleksandr Kuzminsky, Stewart Smith, Vadim Tkachenko,
|
||||
Yasufumi Kinoshita, Ignacio Nin and Baron Schwartz.
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; version 2 of the License.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
|
||||
|
||||
*******************************************************/
|
||||
|
||||
/* Page write filters implementation */
|
||||
|
||||
#include <my_base.h>
|
||||
#include "common.h"
|
||||
#include "write_filt.h"
|
||||
#include "fil_cur.h"
|
||||
#include "xtrabackup.h"
|
||||
|
||||
/************************************************************************
|
||||
Write-through page write filter. */
|
||||
static my_bool wf_wt_init(xb_write_filt_ctxt_t *ctxt, char *dst_name,
|
||||
xb_fil_cur_t *cursor);
|
||||
static my_bool wf_wt_process(xb_write_filt_ctxt_t *ctxt, ds_file_t *dstfile);
|
||||
|
||||
xb_write_filt_t wf_write_through = {
|
||||
&wf_wt_init,
|
||||
&wf_wt_process,
|
||||
NULL,
|
||||
NULL
|
||||
};
|
||||
|
||||
/************************************************************************
|
||||
Incremental page write filter. */
|
||||
static my_bool wf_incremental_init(xb_write_filt_ctxt_t *ctxt, char *dst_name,
|
||||
xb_fil_cur_t *cursor);
|
||||
static my_bool wf_incremental_process(xb_write_filt_ctxt_t *ctxt,
|
||||
ds_file_t *dstfile);
|
||||
static my_bool wf_incremental_finalize(xb_write_filt_ctxt_t *ctxt,
|
||||
ds_file_t *dstfile);
|
||||
static void wf_incremental_deinit(xb_write_filt_ctxt_t *ctxt);
|
||||
|
||||
xb_write_filt_t wf_incremental = {
|
||||
&wf_incremental_init,
|
||||
&wf_incremental_process,
|
||||
&wf_incremental_finalize,
|
||||
&wf_incremental_deinit
|
||||
};
|
||||
|
||||
/************************************************************************
|
||||
Initialize incremental page write filter.
|
||||
|
||||
@return TRUE on success, FALSE on error. */
|
||||
static my_bool
|
||||
wf_incremental_init(xb_write_filt_ctxt_t *ctxt, char *dst_name,
|
||||
xb_fil_cur_t *cursor)
|
||||
{
|
||||
char meta_name[FN_REFLEN];
|
||||
xb_delta_info_t info;
|
||||
ulint buf_size;
|
||||
xb_wf_incremental_ctxt_t *cp =
|
||||
&(ctxt->u.wf_incremental_ctxt);
|
||||
|
||||
ctxt->cursor = cursor;
|
||||
|
||||
/* allocate buffer for incremental backup (4096 pages) */
|
||||
buf_size = (cursor->page_size / 4 + 1) * cursor->page_size;
|
||||
cp->delta_buf_base = static_cast<byte *>(ut_malloc(buf_size));
|
||||
memset(cp->delta_buf_base, 0, buf_size);
|
||||
cp->delta_buf = static_cast<byte *>
|
||||
(ut_align(cp->delta_buf_base, UNIV_PAGE_SIZE_MAX));
|
||||
|
||||
/* write delta meta info */
|
||||
snprintf(meta_name, sizeof(meta_name), "%s%s", dst_name,
|
||||
XB_DELTA_INFO_SUFFIX);
|
||||
info.page_size = cursor->page_size;
|
||||
info.zip_size = cursor->zip_size;
|
||||
info.space_id = cursor->space_id;
|
||||
if (!xb_write_delta_metadata(meta_name, &info)) {
|
||||
msg("[%02u] xtrabackup: Error: "
|
||||
"failed to write meta info for %s\n",
|
||||
cursor->thread_n, cursor->rel_path);
|
||||
return(FALSE);
|
||||
}
|
||||
|
||||
/* change the target file name, since we are only going to write
|
||||
delta pages */
|
||||
strcat(dst_name, ".delta");
|
||||
|
||||
mach_write_to_4(cp->delta_buf, 0x78747261UL); /*"xtra"*/
|
||||
cp->npages = 1;
|
||||
|
||||
return(TRUE);
|
||||
}
|
||||
|
||||
/************************************************************************
|
||||
Run the next batch of pages through incremental page write filter.
|
||||
|
||||
@return TRUE on success, FALSE on error. */
|
||||
static my_bool
|
||||
wf_incremental_process(xb_write_filt_ctxt_t *ctxt, ds_file_t *dstfile)
|
||||
{
|
||||
ulint i;
|
||||
xb_fil_cur_t *cursor = ctxt->cursor;
|
||||
ulint page_size = cursor->page_size;
|
||||
byte *page;
|
||||
xb_wf_incremental_ctxt_t *cp = &(ctxt->u.wf_incremental_ctxt);
|
||||
|
||||
for (i = 0, page = cursor->buf; i < cursor->buf_npages;
|
||||
i++, page += page_size) {
|
||||
|
||||
if (incremental_lsn >= mach_read_from_8(page + FIL_PAGE_LSN)) {
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
/* updated page */
|
||||
if (cp->npages == page_size / 4) {
|
||||
/* flush buffer */
|
||||
if (ds_write(dstfile, cp->delta_buf,
|
||||
cp->npages * page_size)) {
|
||||
return(FALSE);
|
||||
}
|
||||
|
||||
/* clear buffer */
|
||||
memset(cp->delta_buf, 0, page_size / 4 * page_size);
|
||||
/*"xtra"*/
|
||||
mach_write_to_4(cp->delta_buf, 0x78747261UL);
|
||||
cp->npages = 1;
|
||||
}
|
||||
|
||||
mach_write_to_4(cp->delta_buf + cp->npages * 4,
|
||||
cursor->buf_page_no + i);
|
||||
memcpy(cp->delta_buf + cp->npages * page_size, page,
|
||||
page_size);
|
||||
|
||||
cp->npages++;
|
||||
}
|
||||
|
||||
return(TRUE);
|
||||
}
|
||||
|
||||
/************************************************************************
|
||||
Flush the incremental page write filter's buffer.
|
||||
|
||||
@return TRUE on success, FALSE on error. */
|
||||
static my_bool
|
||||
wf_incremental_finalize(xb_write_filt_ctxt_t *ctxt, ds_file_t *dstfile)
|
||||
{
|
||||
xb_fil_cur_t *cursor = ctxt->cursor;
|
||||
ulint page_size = cursor->page_size;
|
||||
xb_wf_incremental_ctxt_t *cp = &(ctxt->u.wf_incremental_ctxt);
|
||||
|
||||
if (cp->npages != page_size / 4) {
|
||||
mach_write_to_4(cp->delta_buf + cp->npages * 4, 0xFFFFFFFFUL);
|
||||
}
|
||||
|
||||
/* Mark the final block */
|
||||
mach_write_to_4(cp->delta_buf, 0x58545241UL); /*"XTRA"*/
|
||||
|
||||
/* flush buffer */
|
||||
if (ds_write(dstfile, cp->delta_buf, cp->npages * page_size)) {
|
||||
return(FALSE);
|
||||
}
|
||||
|
||||
return(TRUE);
|
||||
}
|
||||
|
||||
/************************************************************************
|
||||
Free the incremental page write filter's buffer. */
|
||||
static void
|
||||
wf_incremental_deinit(xb_write_filt_ctxt_t *ctxt)
|
||||
{
|
||||
xb_wf_incremental_ctxt_t *cp = &(ctxt->u.wf_incremental_ctxt);
|
||||
|
||||
if (cp->delta_buf_base != NULL) {
|
||||
ut_free(cp->delta_buf_base);
|
||||
}
|
||||
}
|
||||
|
||||
/************************************************************************
|
||||
Initialize the write-through page write filter.
|
||||
|
||||
@return TRUE on success, FALSE on error. */
|
||||
static my_bool
|
||||
wf_wt_init(xb_write_filt_ctxt_t *ctxt, char *dst_name __attribute__((unused)),
|
||||
xb_fil_cur_t *cursor)
|
||||
{
|
||||
ctxt->cursor = cursor;
|
||||
|
||||
return(TRUE);
|
||||
}
|
||||
|
||||
/************************************************************************
|
||||
Write the next batch of pages to the destination datasink.
|
||||
|
||||
@return TRUE on success, FALSE on error. */
|
||||
static my_bool
|
||||
wf_wt_process(xb_write_filt_ctxt_t *ctxt, ds_file_t *dstfile)
|
||||
{
|
||||
xb_fil_cur_t *cursor = ctxt->cursor;
|
||||
|
||||
if (ds_write(dstfile, cursor->buf, cursor->buf_read)) {
|
||||
return(FALSE);
|
||||
}
|
||||
|
||||
return(TRUE);
|
||||
}
|
58
extra/mariabackup/write_filt.h
Normal file
58
extra/mariabackup/write_filt.h
Normal file
|
@ -0,0 +1,58 @@
|
|||
/******************************************************
|
||||
XtraBackup: hot backup tool for InnoDB
|
||||
(c) 2009-2013 Percona LLC and/or its affiliates.
|
||||
Originally Created 3/3/2009 Yasufumi Kinoshita
|
||||
Written by Alexey Kopytov, Aleksandr Kuzminsky, Stewart Smith, Vadim Tkachenko,
|
||||
Yasufumi Kinoshita, Ignacio Nin and Baron Schwartz.
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; version 2 of the License.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
|
||||
|
||||
*******************************************************/
|
||||
|
||||
/* Page write filter interface */
|
||||
|
||||
#ifndef XB_WRITE_FILT_H
|
||||
#define XB_WRITE_FILT_H
|
||||
|
||||
#include "fil_cur.h"
|
||||
#include "datasink.h"
|
||||
|
||||
/* Incremental page filter context */
|
||||
typedef struct {
|
||||
byte *delta_buf_base;
|
||||
byte *delta_buf;
|
||||
ulint npages;
|
||||
} xb_wf_incremental_ctxt_t;
|
||||
|
||||
/* Page filter context used as an opaque structure by callers */
|
||||
typedef struct {
|
||||
xb_fil_cur_t *cursor;
|
||||
union {
|
||||
xb_wf_incremental_ctxt_t wf_incremental_ctxt;
|
||||
} u;
|
||||
} xb_write_filt_ctxt_t;
|
||||
|
||||
|
||||
typedef struct {
|
||||
my_bool (*init)(xb_write_filt_ctxt_t *ctxt, char *dst_name,
|
||||
xb_fil_cur_t *cursor);
|
||||
my_bool (*process)(xb_write_filt_ctxt_t *ctxt, ds_file_t *dstfile);
|
||||
my_bool (*finalize)(xb_write_filt_ctxt_t *, ds_file_t *dstfile);
|
||||
void (*deinit)(xb_write_filt_ctxt_t *);
|
||||
} xb_write_filt_t;
|
||||
|
||||
extern xb_write_filt_t wf_write_through;
|
||||
extern xb_write_filt_t wf_incremental;
|
||||
|
||||
#endif /* XB_WRITE_FILT_H */
|
220
extra/mariabackup/wsrep.cc
Normal file
220
extra/mariabackup/wsrep.cc
Normal file
|
@ -0,0 +1,220 @@
|
|||
/******************************************************
|
||||
Percona XtraBackup: hot backup tool for InnoDB
|
||||
(c) 2009-2014 Percona LLC and/or its affiliates
|
||||
Originally Created 3/3/2009 Yasufumi Kinoshita
|
||||
Written by Alexey Kopytov, Aleksandr Kuzminsky, Stewart Smith, Vadim Tkachenko,
|
||||
Yasufumi Kinoshita, Ignacio Nin and Baron Schwartz.
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; version 2 of the License.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
|
||||
|
||||
*******************************************************
|
||||
|
||||
This file incorporates work covered by the following copyright and
|
||||
permission notice:
|
||||
|
||||
Copyright 2010 Codership Oy <http://www.codership.com>
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; version 2 of the License.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
|
||||
|
||||
*******************************************************/
|
||||
|
||||
#include <mysql_version.h>
|
||||
#include <my_base.h>
|
||||
#include <handler.h>
|
||||
#include <trx0sys.h>
|
||||
|
||||
#include "common.h"
|
||||
#ifdef WITH_WSREP
|
||||
#define WSREP_XID_PREFIX "WSREPXid"
|
||||
#define WSREP_XID_PREFIX_LEN MYSQL_XID_PREFIX_LEN
|
||||
#define WSREP_XID_UUID_OFFSET 8
|
||||
#define WSREP_XID_SEQNO_OFFSET (WSREP_XID_UUID_OFFSET + sizeof(wsrep_uuid_t))
|
||||
#define WSREP_XID_GTRID_LEN (WSREP_XID_SEQNO_OFFSET + sizeof(wsrep_seqno_t))
|
||||
|
||||
/*! undefined seqno */
|
||||
#define WSREP_SEQNO_UNDEFINED (-1)
|
||||
|
||||
/*! Name of file where Galera info is stored on recovery */
|
||||
#define XB_GALERA_INFO_FILENAME "xtrabackup_galera_info"
|
||||
|
||||
/* Galera UUID type - for all unique IDs */
|
||||
typedef struct wsrep_uuid {
|
||||
unsigned char data[16];
|
||||
} wsrep_uuid_t;
|
||||
|
||||
/* sequence number of a writeset, etc. */
|
||||
typedef long long wsrep_seqno_t;
|
||||
|
||||
/* Undefined UUID */
|
||||
static const wsrep_uuid_t WSREP_UUID_UNDEFINED = {{0,}};
|
||||
|
||||
/***********************************************************************//**
|
||||
Check if a given WSREP XID is valid.
|
||||
|
||||
@return true if valid.
|
||||
*/
|
||||
static
|
||||
bool
|
||||
wsrep_is_wsrep_xid(
|
||||
/*===============*/
|
||||
const void* xid_ptr)
|
||||
{
|
||||
const XID* xid = reinterpret_cast<const XID*>(xid_ptr);
|
||||
|
||||
return((xid->formatID == 1 &&
|
||||
xid->gtrid_length == WSREP_XID_GTRID_LEN &&
|
||||
xid->bqual_length == 0 &&
|
||||
!memcmp(xid->data, WSREP_XID_PREFIX, WSREP_XID_PREFIX_LEN)));
|
||||
}
|
||||
|
||||
/***********************************************************************//**
|
||||
Retrieve binary WSREP UUID from XID.
|
||||
|
||||
@return binary WSREP UUID represenataion, if UUID is valid, or
|
||||
WSREP_UUID_UNDEFINED otherwise.
|
||||
*/
|
||||
static
|
||||
const wsrep_uuid_t*
|
||||
wsrep_xid_uuid(
|
||||
/*===========*/
|
||||
const XID* xid)
|
||||
{
|
||||
if (wsrep_is_wsrep_xid(xid)) {
|
||||
return(reinterpret_cast<const wsrep_uuid_t*>
|
||||
(xid->data + WSREP_XID_UUID_OFFSET));
|
||||
} else {
|
||||
return(&WSREP_UUID_UNDEFINED);
|
||||
}
|
||||
}
|
||||
|
||||
/***********************************************************************//**
|
||||
Retrieve WSREP seqno from XID.
|
||||
|
||||
@return WSREP seqno, if it is valid, or WSREP_SEQNO_UNDEFINED otherwise.
|
||||
*/
|
||||
wsrep_seqno_t wsrep_xid_seqno(
|
||||
/*==========================*/
|
||||
const XID* xid)
|
||||
{
|
||||
if (wsrep_is_wsrep_xid(xid)) {
|
||||
wsrep_seqno_t seqno;
|
||||
memcpy(&seqno, xid->data + WSREP_XID_SEQNO_OFFSET,
|
||||
sizeof(wsrep_seqno_t));
|
||||
|
||||
return(seqno);
|
||||
} else {
|
||||
return(WSREP_SEQNO_UNDEFINED);
|
||||
}
|
||||
}
|
||||
|
||||
/***********************************************************************//**
|
||||
Write UUID to string.
|
||||
|
||||
@return length of UUID string representation or -EMSGSIZE if string is too
|
||||
short.
|
||||
*/
|
||||
static
|
||||
int
|
||||
wsrep_uuid_print(
|
||||
/*=============*/
|
||||
const wsrep_uuid_t* uuid,
|
||||
char* str,
|
||||
size_t str_len)
|
||||
{
|
||||
if (str_len > 36) {
|
||||
const unsigned char* u = uuid->data;
|
||||
return snprintf(str, str_len,
|
||||
"%02x%02x%02x%02x-%02x%02x-%02x%02x-"
|
||||
"%02x%02x-%02x%02x%02x%02x%02x%02x",
|
||||
u[ 0], u[ 1], u[ 2], u[ 3], u[ 4], u[ 5], u[ 6],
|
||||
u[ 7], u[ 8], u[ 9], u[10], u[11], u[12], u[13],
|
||||
u[14], u[15]);
|
||||
}
|
||||
else {
|
||||
return -EMSGSIZE;
|
||||
}
|
||||
}
|
||||
|
||||
/***********************************************************************
|
||||
Store Galera checkpoint info in the 'xtrabackup_galera_info' file, if that
|
||||
information is present in the trx system header. Otherwise, do nothing. */
|
||||
void
|
||||
xb_write_galera_info(bool incremental_prepare)
|
||||
/*==================*/
|
||||
{
|
||||
FILE* fp;
|
||||
XID xid;
|
||||
char uuid_str[40];
|
||||
wsrep_seqno_t seqno;
|
||||
MY_STAT statinfo;
|
||||
|
||||
/* Do not overwrite existing an existing file to be compatible with
|
||||
servers with older server versions */
|
||||
if (!incremental_prepare &&
|
||||
my_stat(XB_GALERA_INFO_FILENAME, &statinfo, MYF(0)) != NULL) {
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
memset(&xid, 0, sizeof(xid));
|
||||
xid.formatID = -1;
|
||||
|
||||
if (!trx_sys_read_wsrep_checkpoint(&xid)) {
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
if (wsrep_uuid_print(wsrep_xid_uuid(&xid), uuid_str,
|
||||
sizeof(uuid_str)) < 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
fp = fopen(XB_GALERA_INFO_FILENAME, "w");
|
||||
if (fp == NULL) {
|
||||
|
||||
msg("xtrabackup: error: "
|
||||
"could not create " XB_GALERA_INFO_FILENAME
|
||||
", errno = %d\n",
|
||||
errno);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
seqno = wsrep_xid_seqno(&xid);
|
||||
|
||||
msg("xtrabackup: Recovered WSREP position: %s:%lld\n",
|
||||
uuid_str, (long long) seqno);
|
||||
|
||||
if (fprintf(fp, "%s:%lld", uuid_str, (long long) seqno) < 0) {
|
||||
|
||||
msg("xtrabackup: error: "
|
||||
"could not write to " XB_GALERA_INFO_FILENAME
|
||||
", errno = %d\n",
|
||||
errno);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
fclose(fp);
|
||||
}
|
||||
#endif
|
32
extra/mariabackup/wsrep.h
Normal file
32
extra/mariabackup/wsrep.h
Normal file
|
@ -0,0 +1,32 @@
|
|||
/******************************************************
|
||||
Percona XtraBackup: hot backup tool for InnoDB
|
||||
(c) 2009-2014 Percona LLC and/or its affiliates
|
||||
Originally Created 3/3/2009 Yasufumi Kinoshita
|
||||
Written by Alexey Kopytov, Aleksandr Kuzminsky, Stewart Smith, Vadim Tkachenko,
|
||||
Yasufumi Kinoshita, Ignacio Nin and Baron Schwartz.
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; version 2 of the License.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
|
||||
*******************************************************/
|
||||
|
||||
#ifndef WSREP_H
|
||||
#define WSREP_H
|
||||
|
||||
/***********************************************************************
|
||||
Store Galera checkpoint info in the 'xtrabackup_galera_info' file, if that
|
||||
information is present in the trx system header. Otherwise, do nothing. */
|
||||
void
|
||||
xb_write_galera_info(bool incremental_prepare);
|
||||
/*==================*/
|
||||
|
||||
#endif
|
78
extra/mariabackup/xb0xb.h
Normal file
78
extra/mariabackup/xb0xb.h
Normal file
|
@ -0,0 +1,78 @@
|
|||
/******************************************************
|
||||
Copyright (c) 2012 Percona LLC and/or its affiliates.
|
||||
|
||||
Declarations of XtraBackup functions called by InnoDB code.
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; version 2 of the License.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
|
||||
|
||||
*******************************************************/
|
||||
|
||||
#ifndef xb0xb_h
|
||||
#define xb0xb_h
|
||||
|
||||
|
||||
extern void os_io_init_simple(void);
|
||||
extern os_file_t files[1000];
|
||||
extern const char *innodb_checksum_algorithm_names[];
|
||||
extern TYPELIB innodb_checksum_algorithm_typelib;
|
||||
extern dberr_t open_or_create_data_files(
|
||||
ibool* create_new_db,
|
||||
#ifdef UNIV_LOG_ARCHIVE
|
||||
lsn_t* min_arch_log_no,
|
||||
lsn_t* max_arch_log_no,
|
||||
#endif
|
||||
lsn_t* min_flushed_lsn,
|
||||
lsn_t* max_flushed_lsn,
|
||||
ulint* sum_of_new_sizes)
|
||||
;
|
||||
int
|
||||
fil_file_readdir_next_file(
|
||||
/*=======================*/
|
||||
dberr_t* err, /*!< out: this is set to DB_ERROR if an error
|
||||
was encountered, otherwise not changed */
|
||||
const char* dirname,/*!< in: directory name or path */
|
||||
os_file_dir_t dir, /*!< in: directory stream */
|
||||
os_file_stat_t* info) /*!< in/out: buffer where the
|
||||
info is returned */;
|
||||
buf_block_t* btr_node_ptr_get_child(
|
||||
const rec_t* node_ptr,/*!< in: node pointer */
|
||||
dict_index_t* index, /*!< in: index */
|
||||
const ulint* offsets,/*!< in: array returned by rec_get_offsets() */
|
||||
mtr_t* mtr) /*!< in: mtr */;
|
||||
|
||||
buf_block_t*
|
||||
btr_root_block_get(
|
||||
/*===============*/
|
||||
const dict_index_t* index, /*!< in: index tree */
|
||||
ulint mode, /*!< in: either RW_S_LATCH
|
||||
or RW_X_LATCH */
|
||||
mtr_t* mtr) /*!< in: mtr */;
|
||||
fil_space_t*
|
||||
fil_space_get_by_name(const char *);
|
||||
ibool
|
||||
recv_check_cp_is_consistent(const byte* buf);
|
||||
void
|
||||
innodb_log_checksum_func_update(
|
||||
/*============================*/
|
||||
ulint algorithm) /*!< in: algorithm */;
|
||||
dberr_t recv_find_max_checkpoint(log_group_t** max_group, ulint* max_field);
|
||||
dberr_t
|
||||
srv_undo_tablespaces_init(
|
||||
/*======================*/
|
||||
ibool create_new_db,
|
||||
ibool backup_mode,
|
||||
const ulint n_conf_tablespaces,
|
||||
ulint* n_opened);
|
||||
|
||||
#endif
|
48
extra/mariabackup/xb_regex.h
Normal file
48
extra/mariabackup/xb_regex.h
Normal file
|
@ -0,0 +1,48 @@
|
|||
/******************************************************
|
||||
Copyright (c) 2011-2013 Percona LLC and/or its affiliates.
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; version 2 of the License.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
|
||||
|
||||
*******************************************************/
|
||||
|
||||
/* This file is required to abstract away regex(3) calls so that
|
||||
my_regex is used on Windows and native calls are used on POSIX platforms. */
|
||||
|
||||
#ifndef XB_REGEX_H
|
||||
#define XB_REGEX_H
|
||||
|
||||
#ifdef HAVE_SYSTEM_REGEX
|
||||
#include <regex.h>
|
||||
#else
|
||||
#include <pcreposix.h>
|
||||
#endif
|
||||
|
||||
typedef regex_t* xb_regex_t;
|
||||
|
||||
#define xb_regex_init()
|
||||
|
||||
#define xb_regexec(preg,string,nmatch,pmatch,eflags) \
|
||||
regexec(preg, string, nmatch, pmatch, eflags)
|
||||
|
||||
#define xb_regerror(errcode,preg,errbuf,errbuf_size) \
|
||||
regerror(errcode, preg, errbuf, errbuf_size)
|
||||
|
||||
#define xb_regcomp(preg,regex,cflags) \
|
||||
regcomp(preg, regex, cflags)
|
||||
|
||||
#define xb_regfree(preg) regfree(preg)
|
||||
|
||||
#define xb_regex_end()
|
||||
|
||||
#endif /* XB_REGEX_H */
|
2721
extra/mariabackup/xbcloud.cc
Normal file
2721
extra/mariabackup/xbcloud.cc
Normal file
File diff suppressed because it is too large
Load diff
696
extra/mariabackup/xbcrypt.c
Normal file
696
extra/mariabackup/xbcrypt.c
Normal file
|
@ -0,0 +1,696 @@
|
|||
/******************************************************
|
||||
Copyright (c) 2013 Percona LLC and/or its affiliates.
|
||||
|
||||
The xbcrypt utility: decrypt files in the XBCRYPT format.
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; version 2 of the License.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
|
||||
|
||||
*******************************************************/
|
||||
|
||||
#include <my_base.h>
|
||||
#include <my_getopt.h>
|
||||
#include "common.h"
|
||||
#include "xbcrypt.h"
|
||||
#include "xbcrypt_common.h"
|
||||
#include "crc_glue.h"
|
||||
|
||||
#if !defined(GCRYPT_VERSION_NUMBER) || (GCRYPT_VERSION_NUMBER < 0x010600)
|
||||
GCRY_THREAD_OPTION_PTHREAD_IMPL;
|
||||
#endif
|
||||
|
||||
#define XBCRYPT_VERSION "1.1"
|
||||
|
||||
typedef enum {
|
||||
RUN_MODE_NONE,
|
||||
RUN_MODE_ENCRYPT,
|
||||
RUN_MODE_DECRYPT
|
||||
} run_mode_t;
|
||||
|
||||
const char *xbcrypt_encrypt_algo_names[] =
|
||||
{ "NONE", "AES128", "AES192", "AES256", NullS};
|
||||
TYPELIB xbcrypt_encrypt_algo_typelib=
|
||||
{array_elements(xbcrypt_encrypt_algo_names)-1,"",
|
||||
xbcrypt_encrypt_algo_names, NULL};
|
||||
|
||||
static run_mode_t opt_run_mode = RUN_MODE_ENCRYPT;
|
||||
static char *opt_input_file = NULL;
|
||||
static char *opt_output_file = NULL;
|
||||
static ulong opt_encrypt_algo;
|
||||
static char *opt_encrypt_key_file = NULL;
|
||||
static void *opt_encrypt_key = NULL;
|
||||
static ulonglong opt_encrypt_chunk_size = 0;
|
||||
static my_bool opt_verbose = FALSE;
|
||||
|
||||
static uint encrypt_algos[] = { GCRY_CIPHER_NONE,
|
||||
GCRY_CIPHER_AES128,
|
||||
GCRY_CIPHER_AES192,
|
||||
GCRY_CIPHER_AES256 };
|
||||
static int encrypt_algo = 0;
|
||||
static int encrypt_mode = GCRY_CIPHER_MODE_CTR;
|
||||
static uint encrypt_key_len = 0;
|
||||
static size_t encrypt_iv_len = 0;
|
||||
|
||||
static struct my_option my_long_options[] =
|
||||
{
|
||||
{"help", '?', "Display this help and exit.",
|
||||
0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0},
|
||||
|
||||
{"decrypt", 'd', "Decrypt data input to output.",
|
||||
0, 0, 0,
|
||||
GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0},
|
||||
|
||||
{"input", 'i', "Optional input file. If not specified, input"
|
||||
" will be read from standard input.",
|
||||
&opt_input_file, &opt_input_file, 0,
|
||||
GET_STR_ALLOC, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
|
||||
|
||||
{"output", 'o', "Optional output file. If not specified, output"
|
||||
" will be written to standard output.",
|
||||
&opt_output_file, &opt_output_file, 0,
|
||||
GET_STR_ALLOC, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
|
||||
|
||||
{"encrypt-algo", 'a', "Encryption algorithm.",
|
||||
&opt_encrypt_algo, &opt_encrypt_algo, &xbcrypt_encrypt_algo_typelib,
|
||||
GET_ENUM, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
|
||||
|
||||
{"encrypt-key", 'k', "Encryption key.",
|
||||
&opt_encrypt_key, &opt_encrypt_key, 0,
|
||||
GET_STR_ALLOC, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
|
||||
|
||||
{"encrypt-key-file", 'f', "File which contains encryption key.",
|
||||
&opt_encrypt_key_file, &opt_encrypt_key_file, 0,
|
||||
GET_STR_ALLOC, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
|
||||
|
||||
{"encrypt-chunk-size", 's', "Size of working buffer for encryption in"
|
||||
" bytes. The default value is 64K.",
|
||||
&opt_encrypt_chunk_size, &opt_encrypt_chunk_size, 0,
|
||||
GET_ULL, REQUIRED_ARG, (1 << 16), 1024, ULONGLONG_MAX, 0, 0, 0},
|
||||
|
||||
{"verbose", 'v', "Display verbose status output.",
|
||||
&opt_verbose, &opt_verbose,
|
||||
0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
|
||||
{0, 0, 0, 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0}
|
||||
};
|
||||
|
||||
static
|
||||
int
|
||||
get_options(int *argc, char ***argv);
|
||||
|
||||
static
|
||||
my_bool
|
||||
get_one_option(int optid, const struct my_option *opt __attribute__((unused)),
|
||||
char *argument __attribute__((unused)));
|
||||
|
||||
static
|
||||
void
|
||||
print_version(void);
|
||||
|
||||
static
|
||||
void
|
||||
usage(void);
|
||||
|
||||
static
|
||||
int
|
||||
mode_decrypt(File filein, File fileout);
|
||||
|
||||
static
|
||||
int
|
||||
mode_encrypt(File filein, File fileout);
|
||||
|
||||
int
|
||||
main(int argc, char **argv)
|
||||
{
|
||||
#if !defined(GCRYPT_VERSION_NUMBER) || (GCRYPT_VERSION_NUMBER < 0x010600)
|
||||
gcry_error_t gcry_error;
|
||||
#endif
|
||||
File filein = 0;
|
||||
File fileout = 0;
|
||||
|
||||
MY_INIT(argv[0]);
|
||||
|
||||
crc_init();
|
||||
|
||||
if (get_options(&argc, &argv)) {
|
||||
goto err;
|
||||
}
|
||||
|
||||
/* Acording to gcrypt docs (and my testing), setting up the threading
|
||||
callbacks must be done first, so, lets give it a shot */
|
||||
#if !defined(GCRYPT_VERSION_NUMBER) || (GCRYPT_VERSION_NUMBER < 0x010600)
|
||||
gcry_error = gcry_control(GCRYCTL_SET_THREAD_CBS, &gcry_threads_pthread);
|
||||
if (gcry_error) {
|
||||
msg("%s: unable to set libgcrypt thread cbs - "
|
||||
"%s : %s\n", my_progname,
|
||||
gcry_strsource(gcry_error),
|
||||
gcry_strerror(gcry_error));
|
||||
return 1;
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Version check should be the very first call because it
|
||||
makes sure that important subsystems are intialized. */
|
||||
if (!gcry_control(GCRYCTL_ANY_INITIALIZATION_P)) {
|
||||
const char *gcrypt_version;
|
||||
gcrypt_version = gcry_check_version(NULL);
|
||||
/* No other library has already initialized libgcrypt. */
|
||||
if (!gcrypt_version) {
|
||||
msg("%s: failed to initialize libgcrypt\n",
|
||||
my_progname);
|
||||
return 1;
|
||||
} else if (opt_verbose) {
|
||||
msg("%s: using gcrypt %s\n", my_progname,
|
||||
gcrypt_version);
|
||||
}
|
||||
}
|
||||
gcry_control(GCRYCTL_DISABLE_SECMEM, 0);
|
||||
gcry_control(GCRYCTL_INITIALIZATION_FINISHED, 0);
|
||||
|
||||
/* Determine the algorithm */
|
||||
encrypt_algo = encrypt_algos[opt_encrypt_algo];
|
||||
|
||||
/* Set up the iv length */
|
||||
encrypt_iv_len = gcry_cipher_get_algo_blklen(encrypt_algo);
|
||||
|
||||
/* Now set up the key */
|
||||
if (opt_encrypt_key == NULL && opt_encrypt_key_file == NULL) {
|
||||
msg("%s: no encryption key or key file specified.\n",
|
||||
my_progname);
|
||||
return 1;
|
||||
} else if (opt_encrypt_key && opt_encrypt_key_file) {
|
||||
msg("%s: both encryption key and key file specified.\n",
|
||||
my_progname);
|
||||
return 1;
|
||||
} else if (opt_encrypt_key_file) {
|
||||
if (!xb_crypt_read_key_file(opt_encrypt_key_file,
|
||||
&opt_encrypt_key,
|
||||
&encrypt_key_len)) {
|
||||
msg("%s: unable to read encryption key file \"%s\".\n",
|
||||
opt_encrypt_key_file, my_progname);
|
||||
return 1;
|
||||
}
|
||||
} else {
|
||||
encrypt_key_len = strlen(opt_encrypt_key);
|
||||
}
|
||||
|
||||
if (opt_input_file) {
|
||||
MY_STAT mystat;
|
||||
|
||||
if (opt_verbose)
|
||||
msg("%s: input file \"%s\".\n", my_progname,
|
||||
opt_input_file);
|
||||
|
||||
if (my_stat(opt_input_file, &mystat, MYF(MY_WME)) == NULL) {
|
||||
goto err;
|
||||
}
|
||||
if (!MY_S_ISREG(mystat.st_mode)) {
|
||||
msg("%s: \"%s\" is not a regular file, exiting.\n",
|
||||
my_progname, opt_input_file);
|
||||
goto err;
|
||||
}
|
||||
if ((filein = my_open(opt_input_file, O_RDONLY, MYF(MY_WME)))
|
||||
< 0) {
|
||||
msg("%s: failed to open \"%s\".\n", my_progname,
|
||||
opt_input_file);
|
||||
goto err;
|
||||
}
|
||||
} else {
|
||||
if (opt_verbose)
|
||||
msg("%s: input from standard input.\n", my_progname);
|
||||
filein = fileno(stdin);
|
||||
}
|
||||
|
||||
if (opt_output_file) {
|
||||
if (opt_verbose)
|
||||
msg("%s: output file \"%s\".\n", my_progname,
|
||||
opt_output_file);
|
||||
|
||||
if ((fileout = my_create(opt_output_file, 0,
|
||||
O_WRONLY|O_BINARY|O_EXCL|O_NOFOLLOW,
|
||||
MYF(MY_WME))) < 0) {
|
||||
msg("%s: failed to create output file \"%s\".\n",
|
||||
my_progname, opt_output_file);
|
||||
goto err;
|
||||
}
|
||||
} else {
|
||||
if (opt_verbose)
|
||||
msg("%s: output to standard output.\n", my_progname);
|
||||
fileout = fileno(stdout);
|
||||
}
|
||||
|
||||
if (opt_run_mode == RUN_MODE_DECRYPT
|
||||
&& mode_decrypt(filein, fileout)) {
|
||||
goto err;
|
||||
} else if (opt_run_mode == RUN_MODE_ENCRYPT
|
||||
&& mode_encrypt(filein, fileout)) {
|
||||
goto err;
|
||||
}
|
||||
|
||||
if (opt_input_file && filein) {
|
||||
my_close(filein, MYF(MY_WME));
|
||||
}
|
||||
if (opt_output_file && fileout) {
|
||||
my_close(fileout, MYF(MY_WME));
|
||||
}
|
||||
|
||||
my_cleanup_options(my_long_options);
|
||||
|
||||
my_end(0);
|
||||
|
||||
return EXIT_SUCCESS;
|
||||
err:
|
||||
if (opt_input_file && filein) {
|
||||
my_close(filein, MYF(MY_WME));
|
||||
}
|
||||
if (opt_output_file && fileout) {
|
||||
my_close(fileout, MYF(MY_WME));
|
||||
}
|
||||
|
||||
my_cleanup_options(my_long_options);
|
||||
|
||||
my_end(0);
|
||||
|
||||
exit(EXIT_FAILURE);
|
||||
|
||||
}
|
||||
|
||||
|
||||
static
|
||||
size_t
|
||||
my_xb_crypt_read_callback(void *userdata, void *buf, size_t len)
|
||||
{
|
||||
File* file = (File *) userdata;
|
||||
return xb_read_full(*file, buf, len);
|
||||
}
|
||||
|
||||
static
|
||||
int
|
||||
mode_decrypt(File filein, File fileout)
|
||||
{
|
||||
xb_rcrypt_t *xbcrypt_file = NULL;
|
||||
void *chunkbuf = NULL;
|
||||
size_t chunksize;
|
||||
size_t originalsize;
|
||||
void *ivbuf = NULL;
|
||||
size_t ivsize;
|
||||
void *decryptbuf = NULL;
|
||||
size_t decryptbufsize = 0;
|
||||
ulonglong ttlchunksread = 0;
|
||||
ulonglong ttlbytesread = 0;
|
||||
xb_rcrypt_result_t result;
|
||||
gcry_cipher_hd_t cipher_handle;
|
||||
gcry_error_t gcry_error;
|
||||
my_bool hash_appended;
|
||||
|
||||
if (encrypt_algo != GCRY_CIPHER_NONE) {
|
||||
gcry_error = gcry_cipher_open(&cipher_handle,
|
||||
encrypt_algo,
|
||||
encrypt_mode, 0);
|
||||
if (gcry_error) {
|
||||
msg("%s:decrypt: unable to open libgcrypt"
|
||||
" cipher - %s : %s\n", my_progname,
|
||||
gcry_strsource(gcry_error),
|
||||
gcry_strerror(gcry_error));
|
||||
return 1;
|
||||
}
|
||||
|
||||
gcry_error = gcry_cipher_setkey(cipher_handle,
|
||||
opt_encrypt_key,
|
||||
encrypt_key_len);
|
||||
if (gcry_error) {
|
||||
msg("%s:decrypt: unable to set libgcrypt cipher"
|
||||
"key - %s : %s\n", my_progname,
|
||||
gcry_strsource(gcry_error),
|
||||
gcry_strerror(gcry_error));
|
||||
goto err;
|
||||
}
|
||||
}
|
||||
|
||||
/* Initialize the xb_crypt format reader */
|
||||
xbcrypt_file = xb_crypt_read_open(&filein, my_xb_crypt_read_callback);
|
||||
if (xbcrypt_file == NULL) {
|
||||
msg("%s:decrypt: xb_crypt_read_open() failed.\n", my_progname);
|
||||
goto err;
|
||||
}
|
||||
|
||||
/* Walk the encrypted chunks, decrypting them and writing out */
|
||||
while ((result = xb_crypt_read_chunk(xbcrypt_file, &chunkbuf,
|
||||
&originalsize, &chunksize,
|
||||
&ivbuf, &ivsize, &hash_appended))
|
||||
== XB_CRYPT_READ_CHUNK) {
|
||||
|
||||
if (encrypt_algo != GCRY_CIPHER_NONE) {
|
||||
gcry_error = gcry_cipher_reset(cipher_handle);
|
||||
if (gcry_error) {
|
||||
msg("%s:decrypt: unable to reset libgcrypt"
|
||||
" cipher - %s : %s\n", my_progname,
|
||||
gcry_strsource(gcry_error),
|
||||
gcry_strerror(gcry_error));
|
||||
goto err;
|
||||
}
|
||||
|
||||
if (ivsize) {
|
||||
gcry_error = gcry_cipher_setctr(cipher_handle,
|
||||
ivbuf,
|
||||
ivsize);
|
||||
}
|
||||
if (gcry_error) {
|
||||
msg("%s:decrypt: unable to set cipher iv - "
|
||||
"%s : %s\n", my_progname,
|
||||
gcry_strsource(gcry_error),
|
||||
gcry_strerror(gcry_error));
|
||||
continue;
|
||||
}
|
||||
|
||||
if (decryptbufsize < originalsize) {
|
||||
decryptbuf = my_realloc(decryptbuf,
|
||||
originalsize,
|
||||
MYF(MY_WME | MY_ALLOW_ZERO_PTR));
|
||||
decryptbufsize = originalsize;
|
||||
}
|
||||
|
||||
/* Try to decrypt it */
|
||||
gcry_error = gcry_cipher_decrypt(cipher_handle,
|
||||
decryptbuf,
|
||||
originalsize,
|
||||
chunkbuf,
|
||||
chunksize);
|
||||
if (gcry_error) {
|
||||
msg("%s:decrypt: unable to decrypt chunk - "
|
||||
"%s : %s\n", my_progname,
|
||||
gcry_strsource(gcry_error),
|
||||
gcry_strerror(gcry_error));
|
||||
gcry_cipher_close(cipher_handle);
|
||||
goto err;
|
||||
}
|
||||
|
||||
} else {
|
||||
decryptbuf = chunkbuf;
|
||||
}
|
||||
|
||||
if (hash_appended) {
|
||||
uchar hash[XB_CRYPT_HASH_LEN];
|
||||
|
||||
originalsize -= XB_CRYPT_HASH_LEN;
|
||||
|
||||
/* ensure that XB_CRYPT_HASH_LEN is the correct length
|
||||
of XB_CRYPT_HASH hashing algorithm output */
|
||||
xb_a(gcry_md_get_algo_dlen(XB_CRYPT_HASH) ==
|
||||
XB_CRYPT_HASH_LEN);
|
||||
gcry_md_hash_buffer(XB_CRYPT_HASH, hash, decryptbuf,
|
||||
originalsize);
|
||||
if (memcmp(hash, (char *) decryptbuf + originalsize,
|
||||
XB_CRYPT_HASH_LEN) != 0) {
|
||||
msg("%s:%s invalid plaintext hash. "
|
||||
"Wrong encrytion key specified?\n",
|
||||
my_progname, __FUNCTION__);
|
||||
result = XB_CRYPT_READ_ERROR;
|
||||
goto err;
|
||||
}
|
||||
}
|
||||
|
||||
/* Write it out */
|
||||
if (my_write(fileout, (const uchar *) decryptbuf, originalsize,
|
||||
MYF(MY_WME | MY_NABP))) {
|
||||
msg("%s:decrypt: unable to write output chunk.\n",
|
||||
my_progname);
|
||||
goto err;
|
||||
}
|
||||
ttlchunksread++;
|
||||
ttlbytesread += chunksize;
|
||||
if (opt_verbose)
|
||||
msg("%s:decrypt: %llu chunks read, %llu bytes read\n.",
|
||||
my_progname, ttlchunksread, ttlbytesread);
|
||||
}
|
||||
|
||||
xb_crypt_read_close(xbcrypt_file);
|
||||
|
||||
if (encrypt_algo != GCRY_CIPHER_NONE)
|
||||
gcry_cipher_close(cipher_handle);
|
||||
|
||||
if (decryptbuf && decryptbufsize)
|
||||
my_free(decryptbuf);
|
||||
|
||||
if (opt_verbose)
|
||||
msg("\n%s:decrypt: done\n", my_progname);
|
||||
|
||||
return 0;
|
||||
err:
|
||||
if (xbcrypt_file)
|
||||
xb_crypt_read_close(xbcrypt_file);
|
||||
|
||||
if (encrypt_algo != GCRY_CIPHER_NONE)
|
||||
gcry_cipher_close(cipher_handle);
|
||||
|
||||
if (decryptbuf && decryptbufsize)
|
||||
my_free(decryptbuf);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static
|
||||
ssize_t
|
||||
my_xb_crypt_write_callback(void *userdata, const void *buf, size_t len)
|
||||
{
|
||||
File* file = (File *) userdata;
|
||||
|
||||
ssize_t ret = my_write(*file, buf, len, MYF(MY_WME));
|
||||
posix_fadvise(*file, 0, 0, POSIX_FADV_DONTNEED);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static
|
||||
int
|
||||
mode_encrypt(File filein, File fileout)
|
||||
{
|
||||
size_t bytesread;
|
||||
size_t chunkbuflen;
|
||||
uchar *chunkbuf = NULL;
|
||||
void *ivbuf = NULL;
|
||||
size_t encryptbuflen = 0;
|
||||
size_t encryptedlen = 0;
|
||||
void *encryptbuf = NULL;
|
||||
ulonglong ttlchunkswritten = 0;
|
||||
ulonglong ttlbyteswritten = 0;
|
||||
xb_wcrypt_t *xbcrypt_file = NULL;
|
||||
gcry_cipher_hd_t cipher_handle;
|
||||
gcry_error_t gcry_error;
|
||||
|
||||
if (encrypt_algo != GCRY_CIPHER_NONE) {
|
||||
gcry_error = gcry_cipher_open(&cipher_handle,
|
||||
encrypt_algo,
|
||||
encrypt_mode, 0);
|
||||
if (gcry_error) {
|
||||
msg("%s:encrypt: unable to open libgcrypt cipher - "
|
||||
"%s : %s\n", my_progname,
|
||||
gcry_strsource(gcry_error),
|
||||
gcry_strerror(gcry_error));
|
||||
return 1;
|
||||
}
|
||||
|
||||
gcry_error = gcry_cipher_setkey(cipher_handle,
|
||||
opt_encrypt_key,
|
||||
encrypt_key_len);
|
||||
if (gcry_error) {
|
||||
msg("%s:encrypt: unable to set libgcrypt cipher key - "
|
||||
"%s : %s\n", my_progname,
|
||||
gcry_strsource(gcry_error),
|
||||
gcry_strerror(gcry_error));
|
||||
goto err;
|
||||
}
|
||||
}
|
||||
|
||||
posix_fadvise(filein, 0, 0, POSIX_FADV_SEQUENTIAL);
|
||||
|
||||
xbcrypt_file = xb_crypt_write_open(&fileout,
|
||||
my_xb_crypt_write_callback);
|
||||
if (xbcrypt_file == NULL) {
|
||||
msg("%s:encrypt: xb_crypt_write_open() failed.\n",
|
||||
my_progname);
|
||||
goto err;
|
||||
}
|
||||
|
||||
ivbuf = my_malloc(encrypt_iv_len, MYF(MY_FAE));
|
||||
|
||||
/* now read in data in chunk size, encrypt and write out */
|
||||
chunkbuflen = opt_encrypt_chunk_size + XB_CRYPT_HASH_LEN;
|
||||
chunkbuf = (uchar *) my_malloc(chunkbuflen, MYF(MY_FAE));
|
||||
while ((bytesread = my_read(filein, chunkbuf, opt_encrypt_chunk_size,
|
||||
MYF(MY_WME))) > 0) {
|
||||
|
||||
size_t origbuflen = bytesread + XB_CRYPT_HASH_LEN;
|
||||
|
||||
/* ensure that XB_CRYPT_HASH_LEN is the correct length
|
||||
of XB_CRYPT_HASH hashing algorithm output */
|
||||
xb_a(XB_CRYPT_HASH_LEN == gcry_md_get_algo_dlen(XB_CRYPT_HASH));
|
||||
gcry_md_hash_buffer(XB_CRYPT_HASH, chunkbuf + bytesread,
|
||||
chunkbuf, bytesread);
|
||||
|
||||
if (encrypt_algo != GCRY_CIPHER_NONE) {
|
||||
gcry_error = gcry_cipher_reset(cipher_handle);
|
||||
|
||||
if (gcry_error) {
|
||||
msg("%s:encrypt: unable to reset cipher - "
|
||||
"%s : %s\n", my_progname,
|
||||
gcry_strsource(gcry_error),
|
||||
gcry_strerror(gcry_error));
|
||||
goto err;
|
||||
}
|
||||
|
||||
xb_crypt_create_iv(ivbuf, encrypt_iv_len);
|
||||
gcry_error = gcry_cipher_setctr(cipher_handle,
|
||||
ivbuf,
|
||||
encrypt_iv_len);
|
||||
|
||||
if (gcry_error) {
|
||||
msg("%s:encrypt: unable to set cipher iv - "
|
||||
"%s : %s\n", my_progname,
|
||||
gcry_strsource(gcry_error),
|
||||
gcry_strerror(gcry_error));
|
||||
continue;
|
||||
}
|
||||
|
||||
if (encryptbuflen < origbuflen) {
|
||||
encryptbuf = my_realloc(encryptbuf, origbuflen,
|
||||
MYF(MY_WME | MY_ALLOW_ZERO_PTR));
|
||||
encryptbuflen = origbuflen;
|
||||
}
|
||||
|
||||
gcry_error = gcry_cipher_encrypt(cipher_handle,
|
||||
encryptbuf,
|
||||
encryptbuflen,
|
||||
chunkbuf,
|
||||
origbuflen);
|
||||
|
||||
encryptedlen = origbuflen;
|
||||
|
||||
if (gcry_error) {
|
||||
msg("%s:encrypt: unable to encrypt chunk - "
|
||||
"%s : %s\n", my_progname,
|
||||
gcry_strsource(gcry_error),
|
||||
gcry_strerror(gcry_error));
|
||||
gcry_cipher_close(cipher_handle);
|
||||
goto err;
|
||||
}
|
||||
} else {
|
||||
encryptedlen = origbuflen;
|
||||
encryptbuf = chunkbuf;
|
||||
}
|
||||
|
||||
if (xb_crypt_write_chunk(xbcrypt_file, encryptbuf,
|
||||
bytesread + XB_CRYPT_HASH_LEN,
|
||||
encryptedlen, ivbuf, encrypt_iv_len)) {
|
||||
msg("%s:encrypt: abcrypt_write_chunk() failed.\n",
|
||||
my_progname);
|
||||
goto err;
|
||||
}
|
||||
|
||||
ttlchunkswritten++;
|
||||
ttlbyteswritten += encryptedlen;
|
||||
|
||||
if (opt_verbose)
|
||||
msg("%s:encrypt: %llu chunks written, %llu bytes "
|
||||
"written\n.", my_progname, ttlchunkswritten,
|
||||
ttlbyteswritten);
|
||||
}
|
||||
|
||||
my_free(ivbuf);
|
||||
my_free(chunkbuf);
|
||||
|
||||
if (encryptbuf && encryptbuflen)
|
||||
my_free(encryptbuf);
|
||||
|
||||
xb_crypt_write_close(xbcrypt_file);
|
||||
|
||||
if (encrypt_algo != GCRY_CIPHER_NONE)
|
||||
gcry_cipher_close(cipher_handle);
|
||||
|
||||
if (opt_verbose)
|
||||
msg("\n%s:encrypt: done\n", my_progname);
|
||||
|
||||
return 0;
|
||||
err:
|
||||
if (chunkbuf)
|
||||
my_free(chunkbuf);
|
||||
|
||||
if (encryptbuf && encryptbuflen)
|
||||
my_free(encryptbuf);
|
||||
|
||||
if (xbcrypt_file)
|
||||
xb_crypt_write_close(xbcrypt_file);
|
||||
|
||||
if (encrypt_algo != GCRY_CIPHER_NONE)
|
||||
gcry_cipher_close(cipher_handle);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static
|
||||
int
|
||||
get_options(int *argc, char ***argv)
|
||||
{
|
||||
int ho_error;
|
||||
|
||||
if ((ho_error= handle_options(argc, argv, my_long_options,
|
||||
get_one_option))) {
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static
|
||||
my_bool
|
||||
get_one_option(int optid, const struct my_option *opt __attribute__((unused)),
|
||||
char *argument __attribute__((unused)))
|
||||
{
|
||||
switch (optid) {
|
||||
case 'd':
|
||||
opt_run_mode = RUN_MODE_DECRYPT;
|
||||
break;
|
||||
case '?':
|
||||
usage();
|
||||
exit(0);
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static
|
||||
void
|
||||
print_version(void)
|
||||
{
|
||||
printf("%s Ver %s for %s (%s)\n", my_progname, XBCRYPT_VERSION,
|
||||
SYSTEM_TYPE, MACHINE_TYPE);
|
||||
}
|
||||
|
||||
static
|
||||
void
|
||||
usage(void)
|
||||
{
|
||||
print_version();
|
||||
puts("Copyright (C) 2011 Percona Inc.");
|
||||
puts("This software comes with ABSOLUTELY NO WARRANTY. "
|
||||
"This is free software,\nand you are welcome to modify and "
|
||||
"redistribute it under the GPL license.\n");
|
||||
|
||||
puts("Encrypt or decrypt files in the XBCRYPT format.\n");
|
||||
|
||||
puts("Usage: ");
|
||||
printf(" %s [OPTIONS...]"
|
||||
" # read data from specified input, encrypting or decrypting "
|
||||
" and writing the result to the specified output.\n",
|
||||
my_progname);
|
||||
puts("\nOptions:");
|
||||
my_print_help(my_long_options);
|
||||
}
|
79
extra/mariabackup/xbcrypt.h
Normal file
79
extra/mariabackup/xbcrypt.h
Normal file
|
@ -0,0 +1,79 @@
|
|||
/******************************************************
|
||||
Copyright (c) 2011 Percona LLC and/or its affiliates.
|
||||
|
||||
Encryption interface for XtraBackup.
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; version 2 of the License.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
|
||||
|
||||
*******************************************************/
|
||||
|
||||
#ifndef XBCRYPT_H
|
||||
#define XBCRYPT_H
|
||||
|
||||
#include <my_base.h>
|
||||
#include "common.h"
|
||||
|
||||
#define XB_CRYPT_CHUNK_MAGIC1 "XBCRYP01"
|
||||
#define XB_CRYPT_CHUNK_MAGIC2 "XBCRYP02"
|
||||
#define XB_CRYPT_CHUNK_MAGIC3 "XBCRYP03" /* must be same size as ^^ */
|
||||
#define XB_CRYPT_CHUNK_MAGIC_CURRENT XB_CRYPT_CHUNK_MAGIC3
|
||||
#define XB_CRYPT_CHUNK_MAGIC_SIZE (sizeof(XB_CRYPT_CHUNK_MAGIC1)-1)
|
||||
|
||||
#define XB_CRYPT_HASH GCRY_MD_SHA256
|
||||
#define XB_CRYPT_HASH_LEN 32
|
||||
|
||||
/******************************************************************************
|
||||
Write interface */
|
||||
typedef struct xb_wcrypt_struct xb_wcrypt_t;
|
||||
|
||||
/* Callback on write for i/o, must return # of bytes written or -1 on error */
|
||||
typedef ssize_t xb_crypt_write_callback(void *userdata,
|
||||
const void *buf, size_t len);
|
||||
|
||||
xb_wcrypt_t *xb_crypt_write_open(void *userdata,
|
||||
xb_crypt_write_callback *onwrite);
|
||||
|
||||
/* Takes buffer, original length, encrypted length iv and iv length, formats
|
||||
output buffer and calls write callback.
|
||||
Returns 0 on success, 1 on error */
|
||||
int xb_crypt_write_chunk(xb_wcrypt_t *crypt, const void *buf, size_t olen,
|
||||
size_t elen, const void *iv, size_t ivlen);
|
||||
|
||||
/* Returns 0 on success, 1 on error */
|
||||
int xb_crypt_write_close(xb_wcrypt_t *crypt);
|
||||
|
||||
/******************************************************************************
|
||||
Read interface */
|
||||
typedef struct xb_rcrypt_struct xb_rcrypt_t;
|
||||
|
||||
/* Callback on read for i/o, must return # of bytes read or -1 on error */
|
||||
typedef size_t xb_crypt_read_callback(void *userdata, void *buf, size_t len);
|
||||
|
||||
xb_rcrypt_t *xb_crypt_read_open(void *userdata,
|
||||
xb_crypt_read_callback *onread);
|
||||
|
||||
typedef enum {
|
||||
XB_CRYPT_READ_CHUNK,
|
||||
XB_CRYPT_READ_INCOMPLETE,
|
||||
XB_CRYPT_READ_EOF,
|
||||
XB_CRYPT_READ_ERROR
|
||||
} xb_rcrypt_result_t;
|
||||
|
||||
xb_rcrypt_result_t xb_crypt_read_chunk(xb_rcrypt_t *crypt, void **buf,
|
||||
size_t *olen, size_t *elen, void **iv,
|
||||
size_t *ivlen, my_bool *hash_appended);
|
||||
|
||||
int xb_crypt_read_close(xb_rcrypt_t *crypt);
|
||||
|
||||
#endif
|
328
extra/mariabackup/xbcrypt_common.c
Normal file
328
extra/mariabackup/xbcrypt_common.c
Normal file
|
@ -0,0 +1,328 @@
|
|||
/******************************************************
|
||||
Copyright (c) 2013, 2017 Percona LLC and/or its affiliates.
|
||||
|
||||
Encryption configuration file interface for XtraBackup.
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; version 2 of the License.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
|
||||
|
||||
*******************************************************/
|
||||
|
||||
#include <my_base.h>
|
||||
#include "common.h"
|
||||
#include "xbcrypt.h"
|
||||
#include "xbcrypt_common.h"
|
||||
|
||||
/* Encryption options */
|
||||
char *ds_encrypt_key = NULL;
|
||||
char *ds_encrypt_key_file = NULL;
|
||||
ulong ds_encrypt_algo;
|
||||
|
||||
static uint encrypt_key_len;
|
||||
static uint encrypt_iv_len;
|
||||
|
||||
static const uint encrypt_mode = GCRY_CIPHER_MODE_CTR;
|
||||
|
||||
static uint encrypt_algos[] = { GCRY_CIPHER_NONE, GCRY_CIPHER_AES128,
|
||||
GCRY_CIPHER_AES192, GCRY_CIPHER_AES256 };
|
||||
static uint encrypt_algo;
|
||||
|
||||
#if !defined(GCRYPT_VERSION_NUMBER) || (GCRYPT_VERSION_NUMBER < 0x010600)
|
||||
GCRY_THREAD_OPTION_PTHREAD_IMPL;
|
||||
#endif
|
||||
|
||||
|
||||
my_bool
|
||||
xb_crypt_read_key_file(const char *filename, void** key, uint *keylength)
|
||||
{
|
||||
FILE *fp;
|
||||
|
||||
if (!(fp = my_fopen(filename, O_RDONLY, MYF(0)))) {
|
||||
msg("%s:%s: unable to open config file \"%s\", errno(%d)\n",
|
||||
my_progname, __FUNCTION__, filename, my_errno);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
fseek(fp, 0 , SEEK_END);
|
||||
*keylength = ftell(fp);
|
||||
rewind(fp);
|
||||
*key = my_malloc(*keylength, MYF(MY_FAE));
|
||||
*keylength = fread(*key, 1, *keylength, fp);
|
||||
my_fclose(fp, MYF(0));
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
void
|
||||
xb_crypt_create_iv(void* ivbuf, size_t ivlen)
|
||||
{
|
||||
gcry_create_nonce(ivbuf, ivlen);
|
||||
}
|
||||
|
||||
gcry_error_t
|
||||
xb_crypt_init(uint *iv_len)
|
||||
{
|
||||
gcry_error_t gcry_error;
|
||||
|
||||
/* Acording to gcrypt docs (and my testing), setting up the threading
|
||||
callbacks must be done first, so, lets give it a shot */
|
||||
#if !defined(GCRYPT_VERSION_NUMBER) || (GCRYPT_VERSION_NUMBER < 0x010600)
|
||||
gcry_error = gcry_control(GCRYCTL_SET_THREAD_CBS, &gcry_threads_pthread);
|
||||
if (gcry_error) {
|
||||
msg("encryption: unable to set libgcrypt thread cbs - "
|
||||
"%s : %s\n",
|
||||
gcry_strsource(gcry_error),
|
||||
gcry_strerror(gcry_error));
|
||||
return gcry_error;
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Version check should be the very next call because it
|
||||
makes sure that important subsystems are intialized. */
|
||||
if (!gcry_control(GCRYCTL_ANY_INITIALIZATION_P)) {
|
||||
const char *gcrypt_version;
|
||||
gcrypt_version = gcry_check_version(NULL);
|
||||
/* No other library has already initialized libgcrypt. */
|
||||
if (!gcrypt_version) {
|
||||
msg("encryption: failed to initialize libgcrypt\n");
|
||||
return 1;
|
||||
} else {
|
||||
msg("encryption: using gcrypt %s\n", gcrypt_version);
|
||||
}
|
||||
}
|
||||
|
||||
/* Disable the gcry secure memory, not dealing with this for now */
|
||||
gcry_error = gcry_control(GCRYCTL_DISABLE_SECMEM, 0);
|
||||
if (gcry_error) {
|
||||
msg("encryption: unable to disable libgcrypt secmem - "
|
||||
"%s : %s\n",
|
||||
gcry_strsource(gcry_error),
|
||||
gcry_strerror(gcry_error));
|
||||
return gcry_error;
|
||||
}
|
||||
|
||||
/* Finalize gcry initialization. */
|
||||
gcry_error = gcry_control(GCRYCTL_INITIALIZATION_FINISHED, 0);
|
||||
if (gcry_error) {
|
||||
msg("encryption: unable to finish libgcrypt initialization - "
|
||||
"%s : %s\n",
|
||||
gcry_strsource(gcry_error),
|
||||
gcry_strerror(gcry_error));
|
||||
return gcry_error;
|
||||
}
|
||||
|
||||
/* Determine the algorithm */
|
||||
encrypt_algo = encrypt_algos[ds_encrypt_algo];
|
||||
|
||||
/* Set up the iv length */
|
||||
encrypt_iv_len = gcry_cipher_get_algo_blklen(encrypt_algo);
|
||||
xb_a(encrypt_iv_len > 0);
|
||||
if (iv_len != NULL) {
|
||||
*iv_len = encrypt_iv_len;
|
||||
}
|
||||
|
||||
/* Now set up the key */
|
||||
if (ds_encrypt_key == NULL &&
|
||||
ds_encrypt_key_file == NULL) {
|
||||
msg("encryption: no encryption key or key file specified.\n");
|
||||
return gcry_error;
|
||||
} else if (ds_encrypt_key && ds_encrypt_key_file) {
|
||||
msg("encryption: both encryption key and key file specified.\n");
|
||||
return gcry_error;
|
||||
} else if (ds_encrypt_key_file) {
|
||||
if (!xb_crypt_read_key_file(ds_encrypt_key_file,
|
||||
(void**)&ds_encrypt_key,
|
||||
&encrypt_key_len)) {
|
||||
msg("encryption: unable to read encryption key file"
|
||||
" \"%s\".\n", ds_encrypt_key_file);
|
||||
return gcry_error;
|
||||
}
|
||||
} else if (ds_encrypt_key) {
|
||||
encrypt_key_len = strlen(ds_encrypt_key);
|
||||
} else {
|
||||
msg("encryption: no encryption key or key file specified.\n");
|
||||
return gcry_error;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
gcry_error_t
|
||||
xb_crypt_cipher_open(gcry_cipher_hd_t *cipher_handle)
|
||||
{
|
||||
if (encrypt_algo != GCRY_CIPHER_NONE) {
|
||||
gcry_error_t gcry_error;
|
||||
|
||||
gcry_error = gcry_cipher_open(cipher_handle,
|
||||
encrypt_algo,
|
||||
encrypt_mode, 0);
|
||||
if (gcry_error) {
|
||||
msg("encryption: unable to open libgcrypt"
|
||||
" cipher - %s : %s\n",
|
||||
gcry_strsource(gcry_error),
|
||||
gcry_strerror(gcry_error));
|
||||
gcry_cipher_close(*cipher_handle);
|
||||
return gcry_error;
|
||||
}
|
||||
|
||||
gcry_error = gcry_cipher_setkey(*cipher_handle,
|
||||
ds_encrypt_key,
|
||||
encrypt_key_len);
|
||||
if (gcry_error) {
|
||||
msg("encryption: unable to set libgcrypt"
|
||||
" cipher key - %s : %s\n",
|
||||
gcry_strsource(gcry_error),
|
||||
gcry_strerror(gcry_error));
|
||||
gcry_cipher_close(*cipher_handle);
|
||||
return gcry_error;
|
||||
}
|
||||
return gcry_error;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
void
|
||||
xb_crypt_cipher_close(gcry_cipher_hd_t cipher_handle)
|
||||
{
|
||||
if (encrypt_algo != GCRY_CIPHER_NONE)
|
||||
gcry_cipher_close(cipher_handle);
|
||||
}
|
||||
|
||||
gcry_error_t
|
||||
xb_crypt_decrypt(gcry_cipher_hd_t cipher_handle, const uchar *from,
|
||||
size_t from_len, uchar *to, size_t *to_len,
|
||||
const uchar *iv, size_t iv_len, my_bool hash_appended)
|
||||
{
|
||||
*to_len = from_len;
|
||||
|
||||
if (encrypt_algo != GCRY_CIPHER_NONE) {
|
||||
|
||||
gcry_error_t gcry_error;
|
||||
|
||||
gcry_error = gcry_cipher_reset(cipher_handle);
|
||||
if (gcry_error) {
|
||||
msg("%s:encryption: unable to reset libgcrypt"
|
||||
" cipher - %s : %s\n", my_progname,
|
||||
gcry_strsource(gcry_error),
|
||||
gcry_strerror(gcry_error));
|
||||
return gcry_error;
|
||||
}
|
||||
|
||||
if (iv_len > 0) {
|
||||
gcry_error = gcry_cipher_setctr(cipher_handle,
|
||||
iv, iv_len);
|
||||
}
|
||||
if (gcry_error) {
|
||||
msg("%s:encryption: unable to set cipher iv - "
|
||||
"%s : %s\n", my_progname,
|
||||
gcry_strsource(gcry_error),
|
||||
gcry_strerror(gcry_error));
|
||||
return gcry_error;
|
||||
}
|
||||
|
||||
/* Try to decrypt it */
|
||||
gcry_error = gcry_cipher_decrypt(cipher_handle, to, *to_len,
|
||||
from, from_len);
|
||||
if (gcry_error) {
|
||||
msg("%s:encryption: unable to decrypt chunk - "
|
||||
"%s : %s\n", my_progname,
|
||||
gcry_strsource(gcry_error),
|
||||
gcry_strerror(gcry_error));
|
||||
gcry_cipher_close(cipher_handle);
|
||||
return gcry_error;
|
||||
}
|
||||
|
||||
if (hash_appended) {
|
||||
uchar hash[XB_CRYPT_HASH_LEN];
|
||||
|
||||
*to_len -= XB_CRYPT_HASH_LEN;
|
||||
|
||||
/* ensure that XB_CRYPT_HASH_LEN is the correct length
|
||||
of XB_CRYPT_HASH hashing algorithm output */
|
||||
xb_ad(gcry_md_get_algo_dlen(XB_CRYPT_HASH) ==
|
||||
XB_CRYPT_HASH_LEN);
|
||||
gcry_md_hash_buffer(XB_CRYPT_HASH, hash, to,
|
||||
*to_len);
|
||||
if (memcmp(hash, (char *) to + *to_len,
|
||||
XB_CRYPT_HASH_LEN) != 0) {
|
||||
msg("%s:%s invalid plaintext hash. "
|
||||
"Wrong encrytion key specified?\n",
|
||||
my_progname, __FUNCTION__);
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
} else {
|
||||
memcpy(to, from, *to_len);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
gcry_error_t
|
||||
xb_crypt_encrypt(gcry_cipher_hd_t cipher_handle, const uchar *from,
|
||||
size_t from_len, uchar *to, size_t *to_len, uchar *iv)
|
||||
{
|
||||
gcry_error_t gcry_error;
|
||||
|
||||
/* ensure that XB_CRYPT_HASH_LEN is the correct length
|
||||
of XB_CRYPT_HASH hashing algorithm output */
|
||||
xb_ad(gcry_md_get_algo_dlen(XB_CRYPT_HASH) ==
|
||||
XB_CRYPT_HASH_LEN);
|
||||
|
||||
memcpy(to, from, from_len);
|
||||
gcry_md_hash_buffer(XB_CRYPT_HASH, to + from_len,
|
||||
from, from_len);
|
||||
|
||||
*to_len = from_len;
|
||||
|
||||
if (encrypt_algo != GCRY_CIPHER_NONE) {
|
||||
|
||||
gcry_error = gcry_cipher_reset(cipher_handle);
|
||||
if (gcry_error) {
|
||||
msg("encrypt: unable to reset cipher - "
|
||||
"%s : %s\n",
|
||||
gcry_strsource(gcry_error),
|
||||
gcry_strerror(gcry_error));
|
||||
return gcry_error;
|
||||
}
|
||||
|
||||
xb_crypt_create_iv(iv, encrypt_iv_len);
|
||||
gcry_error = gcry_cipher_setctr(cipher_handle, iv,
|
||||
encrypt_iv_len);
|
||||
if (gcry_error) {
|
||||
msg("encrypt: unable to set cipher ctr - "
|
||||
"%s : %s\n",
|
||||
gcry_strsource(gcry_error),
|
||||
gcry_strerror(gcry_error));
|
||||
return gcry_error;
|
||||
}
|
||||
|
||||
gcry_error = gcry_cipher_encrypt(cipher_handle, to,
|
||||
*to_len + XB_CRYPT_HASH_LEN,
|
||||
to,
|
||||
from_len + XB_CRYPT_HASH_LEN);
|
||||
if (gcry_error) {
|
||||
msg("encrypt: unable to encrypt buffer - "
|
||||
"%s : %s\n", gcry_strsource(gcry_error),
|
||||
gcry_strerror(gcry_error));
|
||||
return gcry_error;
|
||||
}
|
||||
} else {
|
||||
memcpy(to, from, from_len + XB_CRYPT_HASH_LEN);
|
||||
}
|
||||
|
||||
*to_len += XB_CRYPT_HASH_LEN;
|
||||
|
||||
return 0;
|
||||
}
|
||||
#endif
|
64
extra/mariabackup/xbcrypt_common.h
Normal file
64
extra/mariabackup/xbcrypt_common.h
Normal file
|
@ -0,0 +1,64 @@
|
|||
/******************************************************
|
||||
Copyright (c) 2017 Percona LLC and/or its affiliates.
|
||||
|
||||
Encryption datasink implementation for XtraBackup.
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; version 2 of the License.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
|
||||
|
||||
*******************************************************/
|
||||
|
||||
#include <my_base.h>
|
||||
#if HAVE_GCRYPT
|
||||
#if GCC_VERSION >= 4002
|
||||
/* Workaround to avoid "gcry_ac_* is deprecated" warnings in gcrypt.h */
|
||||
# pragma GCC diagnostic ignored "-Wdeprecated-declarations"
|
||||
#endif
|
||||
|
||||
#include <gcrypt.h>
|
||||
|
||||
extern char *ds_encrypt_key;
|
||||
extern char *ds_encrypt_key_file;
|
||||
extern int ds_encrypt_threads;
|
||||
extern ulong ds_encrypt_algo;
|
||||
|
||||
/******************************************************************************
|
||||
Utility interface */
|
||||
my_bool xb_crypt_read_key_file(const char *filename,
|
||||
void** key, uint *keylength);
|
||||
|
||||
void xb_crypt_create_iv(void* ivbuf, size_t ivlen);
|
||||
|
||||
/* Initialize gcrypt and setup encryption key and IV lengths */
|
||||
gcry_error_t
|
||||
xb_crypt_init(uint *iv_len);
|
||||
|
||||
/* Setup gcrypt cipher */
|
||||
gcry_error_t
|
||||
xb_crypt_cipher_open(gcry_cipher_hd_t *cipher_handle);
|
||||
|
||||
/* Close gcrypt cipher */
|
||||
void
|
||||
xb_crypt_cipher_close(gcry_cipher_hd_t cipher_handle);
|
||||
|
||||
/* Decrypt buffer */
|
||||
gcry_error_t
|
||||
xb_crypt_decrypt(gcry_cipher_hd_t cipher_handle, const uchar *from,
|
||||
size_t from_len, uchar *to, size_t *to_len, const uchar *iv,
|
||||
size_t iv_len, my_bool hash_appended);
|
||||
|
||||
/* Encrypt buffer */
|
||||
gcry_error_t
|
||||
xb_crypt_encrypt(gcry_cipher_hd_t cipher_handle, const uchar *from,
|
||||
size_t from_len, uchar *to, size_t *to_len, uchar *iv);
|
||||
#endif
|
252
extra/mariabackup/xbcrypt_read.c
Normal file
252
extra/mariabackup/xbcrypt_read.c
Normal file
|
@ -0,0 +1,252 @@
|
|||
/******************************************************
|
||||
Copyright (c) 2013 Percona LLC and/or its affiliates.
|
||||
|
||||
The xbcrypt format reader implementation.
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; version 2 of the License.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
|
||||
|
||||
*******************************************************/
|
||||
|
||||
#include "xbcrypt.h"
|
||||
#include "crc_glue.h"
|
||||
|
||||
struct xb_rcrypt_struct {
|
||||
void *userdata;
|
||||
xb_crypt_read_callback *read;
|
||||
void *buffer;
|
||||
size_t bufsize;
|
||||
void *ivbuffer;
|
||||
size_t ivbufsize;
|
||||
ulonglong offset;
|
||||
};
|
||||
|
||||
xb_rcrypt_t *
|
||||
xb_crypt_read_open(void *userdata, xb_crypt_read_callback *onread)
|
||||
{
|
||||
xb_rcrypt_t *crypt;
|
||||
|
||||
xb_ad(onread);
|
||||
|
||||
crypt = (xb_rcrypt_t *) my_malloc(sizeof(xb_rcrypt_t), MYF(MY_FAE));
|
||||
|
||||
crypt->userdata = userdata;
|
||||
crypt->read = onread;
|
||||
crypt->buffer = NULL;
|
||||
crypt->bufsize = 0;
|
||||
crypt->offset = 0;
|
||||
crypt->ivbuffer = NULL;
|
||||
crypt->ivbufsize = 0;
|
||||
return crypt;
|
||||
}
|
||||
|
||||
xb_rcrypt_result_t
|
||||
xb_crypt_read_chunk(xb_rcrypt_t *crypt, void **buf, size_t *olen, size_t *elen,
|
||||
void **iv, size_t *ivlen, my_bool *hash_appended)
|
||||
|
||||
{
|
||||
uchar tmpbuf[XB_CRYPT_CHUNK_MAGIC_SIZE + 8 + 8 + 8 + 4];
|
||||
uchar *ptr;
|
||||
ulonglong tmp;
|
||||
ulong checksum, checksum_exp, version;
|
||||
size_t bytesread;
|
||||
xb_rcrypt_result_t result = XB_CRYPT_READ_CHUNK;
|
||||
|
||||
if ((bytesread = crypt->read(crypt->userdata, tmpbuf, sizeof(tmpbuf)))
|
||||
!= sizeof(tmpbuf)) {
|
||||
if (bytesread == 0) {
|
||||
result = XB_CRYPT_READ_EOF;
|
||||
goto err;
|
||||
} else {
|
||||
msg("%s:%s: unable to read chunk header data at "
|
||||
"offset 0x%llx.\n",
|
||||
my_progname, __FUNCTION__, crypt->offset);
|
||||
result = XB_CRYPT_READ_ERROR;
|
||||
goto err;
|
||||
}
|
||||
}
|
||||
|
||||
ptr = tmpbuf;
|
||||
|
||||
if (memcmp(ptr, XB_CRYPT_CHUNK_MAGIC3,
|
||||
XB_CRYPT_CHUNK_MAGIC_SIZE) == 0) {
|
||||
version = 3;
|
||||
} else if (memcmp(ptr, XB_CRYPT_CHUNK_MAGIC2,
|
||||
XB_CRYPT_CHUNK_MAGIC_SIZE) == 0) {
|
||||
version = 2;
|
||||
} else if (memcmp(ptr, XB_CRYPT_CHUNK_MAGIC1,
|
||||
XB_CRYPT_CHUNK_MAGIC_SIZE) == 0) {
|
||||
version = 1;
|
||||
} else {
|
||||
msg("%s:%s: wrong chunk magic at offset 0x%llx.\n",
|
||||
my_progname, __FUNCTION__, crypt->offset);
|
||||
result = XB_CRYPT_READ_ERROR;
|
||||
goto err;
|
||||
}
|
||||
|
||||
ptr += XB_CRYPT_CHUNK_MAGIC_SIZE;
|
||||
crypt->offset += XB_CRYPT_CHUNK_MAGIC_SIZE;
|
||||
|
||||
tmp = uint8korr(ptr); /* reserved */
|
||||
ptr += 8;
|
||||
crypt->offset += 8;
|
||||
|
||||
tmp = uint8korr(ptr); /* original size */
|
||||
ptr += 8;
|
||||
if (tmp > INT_MAX) {
|
||||
msg("%s:%s: invalid original size at offset 0x%llx.\n",
|
||||
my_progname, __FUNCTION__, crypt->offset);
|
||||
result = XB_CRYPT_READ_ERROR;
|
||||
goto err;
|
||||
}
|
||||
crypt->offset += 8;
|
||||
*olen = (size_t)tmp;
|
||||
|
||||
tmp = uint8korr(ptr); /* encrypted size */
|
||||
ptr += 8;
|
||||
if (tmp > INT_MAX) {
|
||||
msg("%s:%s: invalid encrypted size at offset 0x%llx.\n",
|
||||
my_progname, __FUNCTION__, crypt->offset);
|
||||
result = XB_CRYPT_READ_ERROR;
|
||||
goto err;
|
||||
}
|
||||
crypt->offset += 8;
|
||||
*elen = (size_t)tmp;
|
||||
|
||||
checksum_exp = uint4korr(ptr); /* checksum */
|
||||
ptr += 4;
|
||||
crypt->offset += 4;
|
||||
|
||||
/* iv size */
|
||||
if (version == 1) {
|
||||
*ivlen = 0;
|
||||
*iv = 0;
|
||||
} else {
|
||||
if ((bytesread = crypt->read(crypt->userdata, tmpbuf, 8))
|
||||
!= 8) {
|
||||
if (bytesread == 0) {
|
||||
result = XB_CRYPT_READ_EOF;
|
||||
goto err;
|
||||
} else {
|
||||
msg("%s:%s: unable to read chunk iv size at "
|
||||
"offset 0x%llx.\n",
|
||||
my_progname, __FUNCTION__, crypt->offset);
|
||||
result = XB_CRYPT_READ_ERROR;
|
||||
goto err;
|
||||
}
|
||||
}
|
||||
|
||||
tmp = uint8korr(tmpbuf);
|
||||
if (tmp > INT_MAX) {
|
||||
msg("%s:%s: invalid iv size at offset 0x%llx.\n",
|
||||
my_progname, __FUNCTION__, crypt->offset);
|
||||
result = XB_CRYPT_READ_ERROR;
|
||||
goto err;
|
||||
}
|
||||
crypt->offset += 8;
|
||||
*ivlen = (size_t)tmp;
|
||||
}
|
||||
|
||||
if (*ivlen > crypt->ivbufsize) {
|
||||
crypt->ivbuffer = my_realloc(crypt->ivbuffer, *ivlen,
|
||||
MYF(MY_WME | MY_ALLOW_ZERO_PTR));
|
||||
if (crypt->ivbuffer == NULL) {
|
||||
msg("%s:%s: failed to increase iv buffer to "
|
||||
"%llu bytes.\n", my_progname, __FUNCTION__,
|
||||
(ulonglong)*ivlen);
|
||||
result = XB_CRYPT_READ_ERROR;
|
||||
goto err;
|
||||
}
|
||||
crypt->ivbufsize = *ivlen;
|
||||
}
|
||||
|
||||
if (*ivlen > 0) {
|
||||
if (crypt->read(crypt->userdata, crypt->ivbuffer, *ivlen)
|
||||
!= *ivlen) {
|
||||
msg("%s:%s: failed to read %lld bytes for chunk iv "
|
||||
"at offset 0x%llx.\n", my_progname, __FUNCTION__,
|
||||
(ulonglong)*ivlen, crypt->offset);
|
||||
result = XB_CRYPT_READ_ERROR;
|
||||
goto err;
|
||||
}
|
||||
*iv = crypt->ivbuffer;
|
||||
}
|
||||
|
||||
/* for version euqals 2 we need to read in the iv data but do not init
|
||||
CTR with it */
|
||||
if (version == 2) {
|
||||
*ivlen = 0;
|
||||
*iv = 0;
|
||||
}
|
||||
|
||||
if (*olen > crypt->bufsize) {
|
||||
crypt->buffer = my_realloc(crypt->buffer, *olen,
|
||||
MYF(MY_WME | MY_ALLOW_ZERO_PTR));
|
||||
if (crypt->buffer == NULL) {
|
||||
msg("%s:%s: failed to increase buffer to "
|
||||
"%llu bytes.\n", my_progname, __FUNCTION__,
|
||||
(ulonglong)*olen);
|
||||
result = XB_CRYPT_READ_ERROR;
|
||||
goto err;
|
||||
}
|
||||
crypt->bufsize = *olen;
|
||||
}
|
||||
|
||||
if (*elen > 0) {
|
||||
if (crypt->read(crypt->userdata, crypt->buffer, *elen)
|
||||
!= *elen) {
|
||||
msg("%s:%s: failed to read %lld bytes for chunk payload "
|
||||
"at offset 0x%llx.\n", my_progname, __FUNCTION__,
|
||||
(ulonglong)*elen, crypt->offset);
|
||||
result = XB_CRYPT_READ_ERROR;
|
||||
goto err;
|
||||
}
|
||||
}
|
||||
|
||||
checksum = crc32_iso3309(0, crypt->buffer, *elen);
|
||||
if (checksum != checksum_exp) {
|
||||
msg("%s:%s invalid checksum at offset 0x%llx, "
|
||||
"expected 0x%lx, actual 0x%lx.\n", my_progname, __FUNCTION__,
|
||||
crypt->offset, checksum_exp, checksum);
|
||||
result = XB_CRYPT_READ_ERROR;
|
||||
goto err;
|
||||
}
|
||||
|
||||
crypt->offset += *elen;
|
||||
*buf = crypt->buffer;
|
||||
|
||||
*hash_appended = version > 2;
|
||||
|
||||
goto exit;
|
||||
|
||||
err:
|
||||
*buf = NULL;
|
||||
*olen = 0;
|
||||
*elen = 0;
|
||||
*ivlen = 0;
|
||||
*iv = 0;
|
||||
exit:
|
||||
return result;
|
||||
}
|
||||
|
||||
int xb_crypt_read_close(xb_rcrypt_t *crypt)
|
||||
{
|
||||
if (crypt->buffer)
|
||||
my_free(crypt->buffer);
|
||||
if (crypt->ivbuffer)
|
||||
my_free(crypt->ivbuffer);
|
||||
my_free(crypt);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
105
extra/mariabackup/xbcrypt_write.c
Normal file
105
extra/mariabackup/xbcrypt_write.c
Normal file
|
@ -0,0 +1,105 @@
|
|||
/******************************************************
|
||||
Copyright (c) 2013 Percona LLC and/or its affiliates.
|
||||
|
||||
The xbcrypt format writer implementation.
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; version 2 of the License.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
|
||||
|
||||
*******************************************************/
|
||||
|
||||
#include "xbcrypt.h"
|
||||
#include "crc_glue.h"
|
||||
|
||||
struct xb_wcrypt_struct {
|
||||
void *userdata;
|
||||
xb_crypt_write_callback *write;
|
||||
};
|
||||
|
||||
xb_wcrypt_t *
|
||||
xb_crypt_write_open(void *userdata, xb_crypt_write_callback *onwrite)
|
||||
{
|
||||
xb_wcrypt_t *crypt;
|
||||
|
||||
xb_ad(onwrite);
|
||||
|
||||
crypt = (xb_wcrypt_t *) my_malloc(sizeof(xb_wcrypt_t), MYF(MY_FAE));
|
||||
|
||||
crypt->userdata = userdata;
|
||||
crypt->write = onwrite;
|
||||
|
||||
return crypt;
|
||||
}
|
||||
|
||||
int xb_crypt_write_chunk(xb_wcrypt_t *crypt, const void *buf, size_t olen,
|
||||
size_t elen, const void *iv, size_t ivlen)
|
||||
{
|
||||
uchar tmpbuf[XB_CRYPT_CHUNK_MAGIC_SIZE + 8 + 8 + 8 + 4 + 8];
|
||||
uchar *ptr;
|
||||
ulong checksum;
|
||||
|
||||
xb_ad(olen <= INT_MAX);
|
||||
if (olen > INT_MAX)
|
||||
return 0;
|
||||
|
||||
xb_ad(elen <= INT_MAX);
|
||||
if (elen > INT_MAX)
|
||||
return 0;
|
||||
|
||||
xb_ad(ivlen <= INT_MAX);
|
||||
if (ivlen > INT_MAX)
|
||||
return 0;
|
||||
|
||||
ptr = tmpbuf;
|
||||
|
||||
memcpy(ptr, XB_CRYPT_CHUNK_MAGIC_CURRENT, XB_CRYPT_CHUNK_MAGIC_SIZE);
|
||||
ptr += XB_CRYPT_CHUNK_MAGIC_SIZE;
|
||||
|
||||
int8store(ptr, (ulonglong)0); /* reserved */
|
||||
ptr += 8;
|
||||
|
||||
int8store(ptr, (ulonglong)olen); /* original size */
|
||||
ptr += 8;
|
||||
|
||||
int8store(ptr, (ulonglong)elen); /* encrypted (actual) size */
|
||||
ptr += 8;
|
||||
|
||||
checksum = crc32_iso3309(0, buf, elen);
|
||||
int4store(ptr, checksum); /* checksum */
|
||||
ptr += 4;
|
||||
|
||||
int8store(ptr, (ulonglong)ivlen); /* iv size */
|
||||
ptr += 8;
|
||||
|
||||
xb_ad(ptr <= tmpbuf + sizeof(tmpbuf));
|
||||
|
||||
if (crypt->write(crypt->userdata, tmpbuf, ptr-tmpbuf) == -1)
|
||||
return 1;
|
||||
|
||||
if (crypt->write(crypt->userdata, iv, ivlen) == -1)
|
||||
return 1;
|
||||
|
||||
if (crypt->write(crypt->userdata, buf, elen) == -1)
|
||||
return 1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int xb_crypt_write_close(xb_wcrypt_t *crypt)
|
||||
{
|
||||
my_free(crypt);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
613
extra/mariabackup/xbstream.c
Normal file
613
extra/mariabackup/xbstream.c
Normal file
|
@ -0,0 +1,613 @@
|
|||
/******************************************************
|
||||
Copyright (c) 2011-2013 Percona LLC and/or its affiliates.
|
||||
|
||||
The xbstream utility: serialize/deserialize files in the XBSTREAM format.
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; version 2 of the License.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
|
||||
|
||||
*******************************************************/
|
||||
|
||||
#include <mysql_version.h>
|
||||
#include <my_base.h>
|
||||
#include <my_getopt.h>
|
||||
#include <hash.h>
|
||||
#include <my_pthread.h>
|
||||
#include "common.h"
|
||||
#include "xbstream.h"
|
||||
#include "xbcrypt_common.h"
|
||||
#include "datasink.h"
|
||||
#include "ds_decrypt.h"
|
||||
#include "crc_glue.h"
|
||||
|
||||
#define XBSTREAM_VERSION "1.0"
|
||||
#define XBSTREAM_BUFFER_SIZE (10 * 1024 * 1024UL)
|
||||
|
||||
#define START_FILE_HASH_SIZE 16
|
||||
|
||||
typedef enum {
|
||||
RUN_MODE_NONE,
|
||||
RUN_MODE_CREATE,
|
||||
RUN_MODE_EXTRACT
|
||||
} run_mode_t;
|
||||
|
||||
const char *xbstream_encrypt_algo_names[] =
|
||||
{ "NONE", "AES128", "AES192", "AES256", NullS};
|
||||
TYPELIB xbstream_encrypt_algo_typelib=
|
||||
{array_elements(xbstream_encrypt_algo_names)-1,"",
|
||||
xbstream_encrypt_algo_names, NULL};
|
||||
|
||||
/* Need the following definitions to avoid linking with ds_*.o and their link
|
||||
dependencies */
|
||||
datasink_t datasink_archive;
|
||||
datasink_t datasink_xbstream;
|
||||
datasink_t datasink_compress;
|
||||
datasink_t datasink_tmpfile;
|
||||
datasink_t datasink_encrypt;
|
||||
datasink_t datasink_buffer;
|
||||
|
||||
static run_mode_t opt_mode;
|
||||
static char * opt_directory = NULL;
|
||||
static my_bool opt_verbose = 0;
|
||||
static int opt_parallel = 1;
|
||||
static ulong opt_encrypt_algo;
|
||||
static char *opt_encrypt_key_file = NULL;
|
||||
static void *opt_encrypt_key = NULL;
|
||||
static int opt_encrypt_threads = 1;
|
||||
|
||||
enum {
|
||||
OPT_ENCRYPT_THREADS = 256
|
||||
};
|
||||
|
||||
static struct my_option my_long_options[] =
|
||||
{
|
||||
{"help", '?', "Display this help and exit.",
|
||||
0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0},
|
||||
{"create", 'c', "Stream the specified files to the standard output.",
|
||||
0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0},
|
||||
{"extract", 'x', "Extract to disk files from the stream on the "
|
||||
"standard input.",
|
||||
0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0},
|
||||
{"directory", 'C', "Change the current directory to the specified one "
|
||||
"before streaming or extracting.", &opt_directory, &opt_directory, 0,
|
||||
GET_STR_ALLOC, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
|
||||
{"verbose", 'v', "Print verbose output.", &opt_verbose, &opt_verbose,
|
||||
0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
|
||||
{"parallel", 'p', "Number of worker threads for reading / writing.",
|
||||
&opt_parallel, &opt_parallel, 0, GET_INT, REQUIRED_ARG,
|
||||
1, 1, INT_MAX, 0, 0, 0},
|
||||
{"decrypt", 'd', "Decrypt files ending with .xbcrypt.",
|
||||
&opt_encrypt_algo, &opt_encrypt_algo, &xbstream_encrypt_algo_typelib,
|
||||
GET_ENUM, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
|
||||
{"encrypt-key", 'k', "Encryption key.",
|
||||
&opt_encrypt_key, &opt_encrypt_key, 0,
|
||||
GET_STR_ALLOC, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
|
||||
{"encrypt-key-file", 'f', "File which contains encryption key.",
|
||||
&opt_encrypt_key_file, &opt_encrypt_key_file, 0,
|
||||
GET_STR_ALLOC, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
|
||||
{"encrypt-threads", OPT_ENCRYPT_THREADS,
|
||||
"Number of threads for parallel data encryption. "
|
||||
"The default value is 1.",
|
||||
&opt_encrypt_threads, &opt_encrypt_threads,
|
||||
0, GET_INT, REQUIRED_ARG, 1, 1, INT_MAX, 0, 0, 0},
|
||||
|
||||
{0, 0, 0, 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0}
|
||||
};
|
||||
|
||||
typedef struct {
|
||||
HASH *filehash;
|
||||
xb_rstream_t *stream;
|
||||
ds_ctxt_t *ds_ctxt;
|
||||
ds_ctxt_t *ds_decrypt_ctxt;
|
||||
pthread_mutex_t *mutex;
|
||||
} extract_ctxt_t;
|
||||
|
||||
typedef struct {
|
||||
char *path;
|
||||
uint pathlen;
|
||||
my_off_t offset;
|
||||
ds_file_t *file;
|
||||
pthread_mutex_t mutex;
|
||||
} file_entry_t;
|
||||
|
||||
static int get_options(int *argc, char ***argv);
|
||||
static int mode_create(int argc, char **argv);
|
||||
static int mode_extract(int n_threads, int argc, char **argv);
|
||||
static my_bool get_one_option(int optid, const struct my_option *opt,
|
||||
char *argument);
|
||||
|
||||
int
|
||||
main(int argc, char **argv)
|
||||
{
|
||||
MY_INIT(argv[0]);
|
||||
|
||||
crc_init();
|
||||
|
||||
if (get_options(&argc, &argv)) {
|
||||
goto err;
|
||||
}
|
||||
|
||||
if (opt_mode == RUN_MODE_NONE) {
|
||||
msg("%s: either -c or -x must be specified.\n", my_progname);
|
||||
goto err;
|
||||
}
|
||||
|
||||
/* Change the current directory if -C is specified */
|
||||
if (opt_directory && my_setwd(opt_directory, MYF(MY_WME))) {
|
||||
goto err;
|
||||
}
|
||||
|
||||
if (opt_mode == RUN_MODE_CREATE && mode_create(argc, argv)) {
|
||||
goto err;
|
||||
} else if (opt_mode == RUN_MODE_EXTRACT &&
|
||||
mode_extract(opt_parallel, argc, argv)) {
|
||||
goto err;
|
||||
}
|
||||
|
||||
my_cleanup_options(my_long_options);
|
||||
|
||||
my_end(0);
|
||||
|
||||
return EXIT_SUCCESS;
|
||||
err:
|
||||
my_cleanup_options(my_long_options);
|
||||
|
||||
my_end(0);
|
||||
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
static
|
||||
int
|
||||
get_options(int *argc, char ***argv)
|
||||
{
|
||||
int ho_error;
|
||||
|
||||
if ((ho_error= handle_options(argc, argv, my_long_options,
|
||||
get_one_option))) {
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static
|
||||
void
|
||||
print_version(void)
|
||||
{
|
||||
printf("%s Ver %s for %s (%s)\n", my_progname, XBSTREAM_VERSION,
|
||||
SYSTEM_TYPE, MACHINE_TYPE);
|
||||
}
|
||||
|
||||
static
|
||||
void
|
||||
usage(void)
|
||||
{
|
||||
print_version();
|
||||
puts("Copyright (C) 2011-2013 Percona LLC and/or its affiliates.");
|
||||
puts("This software comes with ABSOLUTELY NO WARRANTY. "
|
||||
"This is free software,\nand you are welcome to modify and "
|
||||
"redistribute it under the GPL license.\n");
|
||||
|
||||
puts("Serialize/deserialize files in the XBSTREAM format.\n");
|
||||
|
||||
puts("Usage: ");
|
||||
printf(" %s -c [OPTIONS...] FILES... # stream specified files to "
|
||||
"standard output.\n", my_progname);
|
||||
printf(" %s -x [OPTIONS...] # extract files from the stream"
|
||||
"on the standard input.\n", my_progname);
|
||||
|
||||
puts("\nOptions:");
|
||||
my_print_help(my_long_options);
|
||||
}
|
||||
|
||||
static
|
||||
int
|
||||
set_run_mode(run_mode_t mode)
|
||||
{
|
||||
if (opt_mode != RUN_MODE_NONE) {
|
||||
msg("%s: can't set specify both -c and -x.\n", my_progname);
|
||||
return 1;
|
||||
}
|
||||
|
||||
opt_mode = mode;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static
|
||||
my_bool
|
||||
get_one_option(int optid, const struct my_option *opt __attribute__((unused)),
|
||||
char *argument __attribute__((unused)))
|
||||
{
|
||||
switch (optid) {
|
||||
case 'c':
|
||||
if (set_run_mode(RUN_MODE_CREATE)) {
|
||||
return TRUE;
|
||||
}
|
||||
break;
|
||||
case 'x':
|
||||
if (set_run_mode(RUN_MODE_EXTRACT)) {
|
||||
return TRUE;
|
||||
}
|
||||
break;
|
||||
case '?':
|
||||
usage();
|
||||
exit(0);
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static
|
||||
int
|
||||
stream_one_file(File file, xb_wstream_file_t *xbfile)
|
||||
{
|
||||
uchar *buf;
|
||||
ssize_t bytes;
|
||||
my_off_t offset;
|
||||
|
||||
posix_fadvise(file, 0, 0, POSIX_FADV_SEQUENTIAL);
|
||||
offset = my_tell(file, MYF(MY_WME));
|
||||
|
||||
buf = (uchar*)(my_malloc(XBSTREAM_BUFFER_SIZE, MYF(MY_FAE)));
|
||||
|
||||
while ((bytes = (ssize_t)my_read(file, buf, XBSTREAM_BUFFER_SIZE,
|
||||
MYF(MY_WME))) > 0) {
|
||||
if (xb_stream_write_data(xbfile, buf, bytes)) {
|
||||
msg("%s: xb_stream_write_data() failed.\n",
|
||||
my_progname);
|
||||
my_free(buf);
|
||||
return 1;
|
||||
}
|
||||
posix_fadvise(file, offset, XBSTREAM_BUFFER_SIZE,
|
||||
POSIX_FADV_DONTNEED);
|
||||
offset += XBSTREAM_BUFFER_SIZE;
|
||||
|
||||
}
|
||||
|
||||
my_free(buf);
|
||||
|
||||
if (bytes < 0) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static
|
||||
int
|
||||
mode_create(int argc, char **argv)
|
||||
{
|
||||
int i;
|
||||
MY_STAT mystat;
|
||||
xb_wstream_t *stream;
|
||||
|
||||
if (argc < 1) {
|
||||
msg("%s: no files are specified.\n", my_progname);
|
||||
return 1;
|
||||
}
|
||||
|
||||
stream = xb_stream_write_new();
|
||||
if (stream == NULL) {
|
||||
msg("%s: xb_stream_write_new() failed.\n", my_progname);
|
||||
return 1;
|
||||
}
|
||||
|
||||
for (i = 0; i < argc; i++) {
|
||||
char *filepath = argv[i];
|
||||
File src_file;
|
||||
xb_wstream_file_t *file;
|
||||
|
||||
if (my_stat(filepath, &mystat, MYF(MY_WME)) == NULL) {
|
||||
goto err;
|
||||
}
|
||||
if (!MY_S_ISREG(mystat.st_mode)) {
|
||||
msg("%s: %s is not a regular file, exiting.\n",
|
||||
my_progname, filepath);
|
||||
goto err;
|
||||
}
|
||||
|
||||
if ((src_file = my_open(filepath, O_RDONLY, MYF(MY_WME))) < 0) {
|
||||
msg("%s: failed to open %s.\n", my_progname, filepath);
|
||||
goto err;
|
||||
}
|
||||
|
||||
file = xb_stream_write_open(stream, filepath, &mystat, NULL, NULL);
|
||||
if (file == NULL) {
|
||||
goto err;
|
||||
}
|
||||
|
||||
if (opt_verbose) {
|
||||
msg("%s\n", filepath);
|
||||
}
|
||||
|
||||
if (stream_one_file(src_file, file) ||
|
||||
xb_stream_write_close(file) ||
|
||||
my_close(src_file, MYF(MY_WME))) {
|
||||
goto err;
|
||||
}
|
||||
}
|
||||
|
||||
xb_stream_write_done(stream);
|
||||
|
||||
return 0;
|
||||
err:
|
||||
xb_stream_write_done(stream);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
/************************************************************************
|
||||
Check if string ends with given suffix.
|
||||
@return true if string ends with given suffix. */
|
||||
static
|
||||
my_bool
|
||||
ends_with(const char *str, const char *suffix)
|
||||
{
|
||||
size_t suffix_len = strlen(suffix);
|
||||
size_t str_len = strlen(str);
|
||||
return(str_len >= suffix_len
|
||||
&& strcmp(str + str_len - suffix_len, suffix) == 0);
|
||||
}
|
||||
|
||||
static
|
||||
file_entry_t *
|
||||
file_entry_new(extract_ctxt_t *ctxt, const char *path, uint pathlen)
|
||||
{
|
||||
file_entry_t *entry;
|
||||
ds_file_t *file;
|
||||
|
||||
entry = (file_entry_t *) my_malloc(sizeof(file_entry_t),
|
||||
MYF(MY_WME | MY_ZEROFILL));
|
||||
if (entry == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
entry->path = my_strndup(path, pathlen, MYF(MY_WME));
|
||||
if (entry->path == NULL) {
|
||||
goto err;
|
||||
}
|
||||
entry->pathlen = pathlen;
|
||||
|
||||
if (ctxt->ds_decrypt_ctxt && ends_with(path, ".xbcrypt")) {
|
||||
file = ds_open(ctxt->ds_decrypt_ctxt, path, NULL);
|
||||
} else {
|
||||
file = ds_open(ctxt->ds_ctxt, path, NULL);
|
||||
}
|
||||
if (file == NULL) {
|
||||
msg("%s: failed to create file.\n", my_progname);
|
||||
goto err;
|
||||
}
|
||||
|
||||
if (opt_verbose) {
|
||||
msg("%s\n", entry->path);
|
||||
}
|
||||
|
||||
entry->file = file;
|
||||
|
||||
pthread_mutex_init(&entry->mutex, NULL);
|
||||
|
||||
return entry;
|
||||
|
||||
err:
|
||||
if (entry->path != NULL) {
|
||||
my_free(entry->path);
|
||||
}
|
||||
my_free(entry);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static
|
||||
uchar *
|
||||
get_file_entry_key(file_entry_t *entry, size_t *length,
|
||||
my_bool not_used __attribute__((unused)))
|
||||
{
|
||||
*length = entry->pathlen;
|
||||
return (uchar *) entry->path;
|
||||
}
|
||||
|
||||
static
|
||||
void
|
||||
file_entry_free(file_entry_t *entry)
|
||||
{
|
||||
pthread_mutex_destroy(&entry->mutex);
|
||||
ds_close(entry->file);
|
||||
my_free(entry->path);
|
||||
my_free(entry);
|
||||
}
|
||||
|
||||
static
|
||||
void *
|
||||
extract_worker_thread_func(void *arg)
|
||||
{
|
||||
xb_rstream_chunk_t chunk;
|
||||
file_entry_t *entry;
|
||||
xb_rstream_result_t res;
|
||||
|
||||
extract_ctxt_t *ctxt = (extract_ctxt_t *) arg;
|
||||
|
||||
my_thread_init();
|
||||
|
||||
memset(&chunk, 0, sizeof(chunk));
|
||||
|
||||
while (1) {
|
||||
|
||||
pthread_mutex_lock(ctxt->mutex);
|
||||
res = xb_stream_read_chunk(ctxt->stream, &chunk);
|
||||
|
||||
if (res != XB_STREAM_READ_CHUNK) {
|
||||
pthread_mutex_unlock(ctxt->mutex);
|
||||
break;
|
||||
}
|
||||
|
||||
/* If unknown type and ignorable flag is set, skip this chunk */
|
||||
if (chunk.type == XB_CHUNK_TYPE_UNKNOWN && \
|
||||
!(chunk.flags & XB_STREAM_FLAG_IGNORABLE)) {
|
||||
pthread_mutex_unlock(ctxt->mutex);
|
||||
continue;
|
||||
}
|
||||
|
||||
/* See if we already have this file open */
|
||||
entry = (file_entry_t *) my_hash_search(ctxt->filehash,
|
||||
(uchar *) chunk.path,
|
||||
chunk.pathlen);
|
||||
|
||||
if (entry == NULL) {
|
||||
entry = file_entry_new(ctxt,
|
||||
chunk.path,
|
||||
chunk.pathlen);
|
||||
if (entry == NULL) {
|
||||
pthread_mutex_unlock(ctxt->mutex);
|
||||
break;
|
||||
}
|
||||
if (my_hash_insert(ctxt->filehash, (uchar *) entry)) {
|
||||
msg("%s: my_hash_insert() failed.\n",
|
||||
my_progname);
|
||||
pthread_mutex_unlock(ctxt->mutex);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
pthread_mutex_lock(&entry->mutex);
|
||||
|
||||
pthread_mutex_unlock(ctxt->mutex);
|
||||
|
||||
res = xb_stream_validate_checksum(&chunk);
|
||||
|
||||
if (res != XB_STREAM_READ_CHUNK) {
|
||||
pthread_mutex_unlock(&entry->mutex);
|
||||
break;
|
||||
}
|
||||
|
||||
if (chunk.type == XB_CHUNK_TYPE_EOF) {
|
||||
pthread_mutex_unlock(&entry->mutex);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (entry->offset != chunk.offset) {
|
||||
msg("%s: out-of-order chunk: real offset = 0x%llx, "
|
||||
"expected offset = 0x%llx\n", my_progname,
|
||||
chunk.offset, entry->offset);
|
||||
pthread_mutex_unlock(&entry->mutex);
|
||||
res = XB_STREAM_READ_ERROR;
|
||||
break;
|
||||
}
|
||||
|
||||
if (ds_write(entry->file, chunk.data, chunk.length)) {
|
||||
msg("%s: my_write() failed.\n", my_progname);
|
||||
pthread_mutex_unlock(&entry->mutex);
|
||||
res = XB_STREAM_READ_ERROR;
|
||||
break;
|
||||
}
|
||||
|
||||
entry->offset += chunk.length;
|
||||
|
||||
pthread_mutex_unlock(&entry->mutex);
|
||||
}
|
||||
|
||||
if (chunk.data)
|
||||
my_free(chunk.data);
|
||||
|
||||
my_thread_end();
|
||||
|
||||
return (void *)(res);
|
||||
}
|
||||
|
||||
|
||||
static
|
||||
int
|
||||
mode_extract(int n_threads, int argc __attribute__((unused)),
|
||||
char **argv __attribute__((unused)))
|
||||
{
|
||||
xb_rstream_t *stream = NULL;
|
||||
HASH filehash;
|
||||
ds_ctxt_t *ds_ctxt = NULL;
|
||||
ds_ctxt_t *ds_decrypt_ctxt = NULL;
|
||||
extract_ctxt_t ctxt;
|
||||
int i;
|
||||
pthread_t *tids = NULL;
|
||||
void **retvals = NULL;
|
||||
pthread_mutex_t mutex;
|
||||
int ret = 0;
|
||||
|
||||
if (my_hash_init(&filehash, &my_charset_bin, START_FILE_HASH_SIZE,
|
||||
0, 0, (my_hash_get_key) get_file_entry_key,
|
||||
(my_hash_free_key) file_entry_free, MYF(0))) {
|
||||
msg("%s: failed to initialize file hash.\n", my_progname);
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (pthread_mutex_init(&mutex, NULL)) {
|
||||
msg("%s: failed to initialize mutex.\n", my_progname);
|
||||
my_hash_free(&filehash);
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* If --directory is specified, it is already set as CWD by now. */
|
||||
ds_ctxt = ds_create(".", DS_TYPE_LOCAL);
|
||||
if (ds_ctxt == NULL) {
|
||||
ret = 1;
|
||||
goto exit;
|
||||
}
|
||||
|
||||
|
||||
stream = xb_stream_read_new();
|
||||
if (stream == NULL) {
|
||||
msg("%s: xb_stream_read_new() failed.\n", my_progname);
|
||||
pthread_mutex_destroy(&mutex);
|
||||
ret = 1;
|
||||
goto exit;
|
||||
}
|
||||
|
||||
ctxt.stream = stream;
|
||||
ctxt.filehash = &filehash;
|
||||
ctxt.ds_ctxt = ds_ctxt;
|
||||
ctxt.ds_decrypt_ctxt = ds_decrypt_ctxt;
|
||||
ctxt.mutex = &mutex;
|
||||
|
||||
tids = malloc(sizeof(pthread_t) * n_threads);
|
||||
retvals = malloc(sizeof(void*) * n_threads);
|
||||
|
||||
for (i = 0; i < n_threads; i++)
|
||||
pthread_create(tids + i, NULL, extract_worker_thread_func,
|
||||
&ctxt);
|
||||
|
||||
for (i = 0; i < n_threads; i++)
|
||||
pthread_join(tids[i], retvals + i);
|
||||
|
||||
for (i = 0; i < n_threads; i++) {
|
||||
if ((ulong)retvals[i] == XB_STREAM_READ_ERROR) {
|
||||
ret = 1;
|
||||
goto exit;
|
||||
}
|
||||
}
|
||||
|
||||
exit:
|
||||
pthread_mutex_destroy(&mutex);
|
||||
|
||||
free(tids);
|
||||
free(retvals);
|
||||
|
||||
my_hash_free(&filehash);
|
||||
if (ds_ctxt != NULL) {
|
||||
ds_destroy(ds_ctxt);
|
||||
}
|
||||
if (ds_decrypt_ctxt) {
|
||||
ds_destroy(ds_decrypt_ctxt);
|
||||
}
|
||||
xb_stream_read_done(stream);
|
||||
|
||||
return ret;
|
||||
}
|
107
extra/mariabackup/xbstream.h
Normal file
107
extra/mariabackup/xbstream.h
Normal file
|
@ -0,0 +1,107 @@
|
|||
/******************************************************
|
||||
Copyright (c) 2011-2017 Percona LLC and/or its affiliates.
|
||||
|
||||
The xbstream format interface.
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; version 2 of the License.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
|
||||
|
||||
*******************************************************/
|
||||
|
||||
#ifndef XBSTREAM_H
|
||||
#define XBSTREAM_H
|
||||
|
||||
#include <my_base.h>
|
||||
|
||||
/* Magic value in a chunk header */
|
||||
#define XB_STREAM_CHUNK_MAGIC "XBSTCK01"
|
||||
|
||||
/* Chunk flags */
|
||||
/* Chunk can be ignored if unknown version/format */
|
||||
#define XB_STREAM_FLAG_IGNORABLE 0x01
|
||||
|
||||
/* Magic + flags + type + path len */
|
||||
#define CHUNK_HEADER_CONSTANT_LEN ((sizeof(XB_STREAM_CHUNK_MAGIC) - 1) + \
|
||||
1 + 1 + 4)
|
||||
#define CHUNK_TYPE_OFFSET (sizeof(XB_STREAM_CHUNK_MAGIC) - 1 + 1)
|
||||
#define PATH_LENGTH_OFFSET (sizeof(XB_STREAM_CHUNK_MAGIC) - 1 + 1 + 1)
|
||||
|
||||
typedef struct xb_wstream_struct xb_wstream_t;
|
||||
|
||||
typedef struct xb_wstream_file_struct xb_wstream_file_t;
|
||||
|
||||
typedef enum {
|
||||
XB_STREAM_FMT_NONE,
|
||||
XB_STREAM_FMT_TAR,
|
||||
XB_STREAM_FMT_XBSTREAM
|
||||
} xb_stream_fmt_t;
|
||||
|
||||
/************************************************************************
|
||||
Write interface. */
|
||||
|
||||
typedef ssize_t xb_stream_write_callback(xb_wstream_file_t *file,
|
||||
void *userdata,
|
||||
const void *buf, size_t len);
|
||||
|
||||
xb_wstream_t *xb_stream_write_new(void);
|
||||
|
||||
xb_wstream_file_t *xb_stream_write_open(xb_wstream_t *stream, const char *path,
|
||||
MY_STAT *mystat, void *userdata,
|
||||
xb_stream_write_callback *onwrite);
|
||||
|
||||
int xb_stream_write_data(xb_wstream_file_t *file, const void *buf, size_t len);
|
||||
|
||||
int xb_stream_write_close(xb_wstream_file_t *file);
|
||||
|
||||
int xb_stream_write_done(xb_wstream_t *stream);
|
||||
|
||||
/************************************************************************
|
||||
Read interface. */
|
||||
|
||||
typedef enum {
|
||||
XB_STREAM_READ_CHUNK,
|
||||
XB_STREAM_READ_EOF,
|
||||
XB_STREAM_READ_ERROR
|
||||
} xb_rstream_result_t;
|
||||
|
||||
typedef enum {
|
||||
XB_CHUNK_TYPE_UNKNOWN = '\0',
|
||||
XB_CHUNK_TYPE_PAYLOAD = 'P',
|
||||
XB_CHUNK_TYPE_EOF = 'E'
|
||||
} xb_chunk_type_t;
|
||||
|
||||
typedef struct xb_rstream_struct xb_rstream_t;
|
||||
|
||||
typedef struct {
|
||||
uchar flags;
|
||||
xb_chunk_type_t type;
|
||||
uint pathlen;
|
||||
char path[FN_REFLEN];
|
||||
size_t length;
|
||||
my_off_t offset;
|
||||
my_off_t checksum_offset;
|
||||
void *data;
|
||||
ulong checksum;
|
||||
size_t buflen;
|
||||
} xb_rstream_chunk_t;
|
||||
|
||||
xb_rstream_t *xb_stream_read_new(void);
|
||||
|
||||
xb_rstream_result_t xb_stream_read_chunk(xb_rstream_t *stream,
|
||||
xb_rstream_chunk_t *chunk);
|
||||
|
||||
int xb_stream_read_done(xb_rstream_t *stream);
|
||||
|
||||
int xb_stream_validate_checksum(xb_rstream_chunk_t *chunk);
|
||||
|
||||
#endif
|
228
extra/mariabackup/xbstream_read.c
Normal file
228
extra/mariabackup/xbstream_read.c
Normal file
|
@ -0,0 +1,228 @@
|
|||
/******************************************************
|
||||
Copyright (c) 2011-2017 Percona LLC and/or its affiliates.
|
||||
|
||||
The xbstream format reader implementation.
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; version 2 of the License.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
|
||||
|
||||
*******************************************************/
|
||||
|
||||
#include <mysql_version.h>
|
||||
#include <my_base.h>
|
||||
#include <zlib.h>
|
||||
#include "common.h"
|
||||
#include "xbstream.h"
|
||||
#include "crc_glue.h"
|
||||
|
||||
/* Allocate 1 MB for the payload buffer initially */
|
||||
#define INIT_BUFFER_LEN (1024 * 1024)
|
||||
|
||||
#ifndef MY_OFF_T_MAX
|
||||
#define MY_OFF_T_MAX (~(my_off_t)0UL)
|
||||
#endif
|
||||
|
||||
struct xb_rstream_struct {
|
||||
my_off_t offset;
|
||||
File fd;
|
||||
};
|
||||
|
||||
xb_rstream_t *
|
||||
xb_stream_read_new(void)
|
||||
{
|
||||
xb_rstream_t *stream;
|
||||
|
||||
stream = (xb_rstream_t *) my_malloc(sizeof(xb_rstream_t), MYF(MY_FAE));
|
||||
|
||||
#ifdef __WIN__
|
||||
setmode(fileno(stdin), _O_BINARY);
|
||||
#endif
|
||||
|
||||
stream->fd = my_fileno(stdin);
|
||||
stream->offset = 0;
|
||||
|
||||
return stream;
|
||||
}
|
||||
|
||||
static inline
|
||||
xb_chunk_type_t
|
||||
validate_chunk_type(uchar code)
|
||||
{
|
||||
switch ((xb_chunk_type_t) code) {
|
||||
case XB_CHUNK_TYPE_PAYLOAD:
|
||||
case XB_CHUNK_TYPE_EOF:
|
||||
return (xb_chunk_type_t) code;
|
||||
default:
|
||||
return XB_CHUNK_TYPE_UNKNOWN;
|
||||
}
|
||||
}
|
||||
|
||||
int
|
||||
xb_stream_validate_checksum(xb_rstream_chunk_t *chunk)
|
||||
{
|
||||
ulong checksum;
|
||||
|
||||
checksum = crc32_iso3309(0, chunk->data, (uint)chunk->length);
|
||||
if (checksum != chunk->checksum) {
|
||||
msg("xb_stream_read_chunk(): invalid checksum at offset "
|
||||
"0x%llx: expected 0x%lx, read 0x%lx.\n",
|
||||
(ulonglong) chunk->checksum_offset, chunk->checksum,
|
||||
checksum);
|
||||
return XB_STREAM_READ_ERROR;
|
||||
}
|
||||
|
||||
return XB_STREAM_READ_CHUNK;
|
||||
}
|
||||
|
||||
#define F_READ(buf,len) \
|
||||
do { \
|
||||
if (xb_read_full(fd, buf, len) < len) { \
|
||||
msg("xb_stream_read_chunk(): my_read() failed.\n"); \
|
||||
goto err; \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
xb_rstream_result_t
|
||||
xb_stream_read_chunk(xb_rstream_t *stream, xb_rstream_chunk_t *chunk)
|
||||
{
|
||||
uchar tmpbuf[16];
|
||||
uchar *ptr = tmpbuf;
|
||||
uint pathlen;
|
||||
size_t tbytes;
|
||||
ulonglong ullval;
|
||||
File fd = stream->fd;
|
||||
|
||||
xb_ad(sizeof(tmpbuf) >= CHUNK_HEADER_CONSTANT_LEN);
|
||||
|
||||
/* This is the only place where we expect EOF, so read with
|
||||
xb_read_full() rather than F_READ() */
|
||||
tbytes = xb_read_full(fd, ptr, CHUNK_HEADER_CONSTANT_LEN);
|
||||
if (tbytes == 0) {
|
||||
return XB_STREAM_READ_EOF;
|
||||
} else if (tbytes < CHUNK_HEADER_CONSTANT_LEN) {
|
||||
msg("xb_stream_read_chunk(): unexpected end of stream at "
|
||||
"offset 0x%llx.\n", stream->offset);
|
||||
goto err;
|
||||
}
|
||||
|
||||
ptr = tmpbuf;
|
||||
|
||||
/* Chunk magic value */
|
||||
if (memcmp(tmpbuf, XB_STREAM_CHUNK_MAGIC, 8)) {
|
||||
msg("xb_stream_read_chunk(): wrong chunk magic at offset "
|
||||
"0x%llx.\n", (ulonglong) stream->offset);
|
||||
goto err;
|
||||
}
|
||||
ptr += 8;
|
||||
stream->offset += 8;
|
||||
|
||||
/* Chunk flags */
|
||||
chunk->flags = *ptr++;
|
||||
stream->offset++;
|
||||
|
||||
/* Chunk type, ignore unknown ones if ignorable flag is set */
|
||||
chunk->type = validate_chunk_type(*ptr);
|
||||
if (chunk->type == XB_CHUNK_TYPE_UNKNOWN &&
|
||||
!(chunk->flags & XB_STREAM_FLAG_IGNORABLE)) {
|
||||
msg("xb_stream_read_chunk(): unknown chunk type 0x%lu at "
|
||||
"offset 0x%llx.\n", (ulong) *ptr,
|
||||
(ulonglong) stream->offset);
|
||||
goto err;
|
||||
}
|
||||
ptr++;
|
||||
stream->offset++;
|
||||
|
||||
/* Path length */
|
||||
pathlen = uint4korr(ptr);
|
||||
if (pathlen >= FN_REFLEN) {
|
||||
msg("xb_stream_read_chunk(): path length (%lu) is too large at "
|
||||
"offset 0x%llx.\n", (ulong) pathlen, stream->offset);
|
||||
goto err;
|
||||
}
|
||||
chunk->pathlen = pathlen;
|
||||
stream->offset +=4;
|
||||
|
||||
xb_ad((ptr + 4 - tmpbuf) == CHUNK_HEADER_CONSTANT_LEN);
|
||||
|
||||
/* Path */
|
||||
if (chunk->pathlen > 0) {
|
||||
F_READ((uchar *) chunk->path, pathlen);
|
||||
stream->offset += pathlen;
|
||||
}
|
||||
chunk->path[pathlen] = '\0';
|
||||
|
||||
if (chunk->type == XB_CHUNK_TYPE_EOF) {
|
||||
return XB_STREAM_READ_CHUNK;
|
||||
}
|
||||
|
||||
/* Payload length */
|
||||
F_READ(tmpbuf, 16);
|
||||
ullval = uint8korr(tmpbuf);
|
||||
if (ullval > (ulonglong) SIZE_T_MAX) {
|
||||
msg("xb_stream_read_chunk(): chunk length is too large at "
|
||||
"offset 0x%llx: 0x%llx.\n", (ulonglong) stream->offset,
|
||||
ullval);
|
||||
goto err;
|
||||
}
|
||||
chunk->length = (size_t) ullval;
|
||||
stream->offset += 8;
|
||||
|
||||
/* Payload offset */
|
||||
ullval = uint8korr(tmpbuf + 8);
|
||||
if (ullval > (ulonglong) MY_OFF_T_MAX) {
|
||||
msg("xb_stream_read_chunk(): chunk offset is too large at "
|
||||
"offset 0x%llx: 0x%llx.\n", (ulonglong) stream->offset,
|
||||
ullval);
|
||||
goto err;
|
||||
}
|
||||
chunk->offset = (my_off_t) ullval;
|
||||
stream->offset += 8;
|
||||
|
||||
/* Reallocate the buffer if needed */
|
||||
if (chunk->length > chunk->buflen) {
|
||||
chunk->data = my_realloc(chunk->data, chunk->length,
|
||||
MYF(MY_WME | MY_ALLOW_ZERO_PTR));
|
||||
if (chunk->data == NULL) {
|
||||
msg("xb_stream_read_chunk(): failed to increase buffer "
|
||||
"to %lu bytes.\n", (ulong) chunk->length);
|
||||
goto err;
|
||||
}
|
||||
chunk->buflen = chunk->length;
|
||||
}
|
||||
|
||||
/* Checksum */
|
||||
F_READ(tmpbuf, 4);
|
||||
chunk->checksum = uint4korr(tmpbuf);
|
||||
chunk->checksum_offset = stream->offset;
|
||||
|
||||
/* Payload */
|
||||
if (chunk->length > 0) {
|
||||
F_READ(chunk->data, chunk->length);
|
||||
stream->offset += chunk->length;
|
||||
}
|
||||
|
||||
stream->offset += 4;
|
||||
|
||||
return XB_STREAM_READ_CHUNK;
|
||||
|
||||
err:
|
||||
return XB_STREAM_READ_ERROR;
|
||||
}
|
||||
|
||||
int
|
||||
xb_stream_read_done(xb_rstream_t *stream)
|
||||
{
|
||||
my_free(stream);
|
||||
|
||||
return 0;
|
||||
}
|
294
extra/mariabackup/xbstream_write.c
Normal file
294
extra/mariabackup/xbstream_write.c
Normal file
|
@ -0,0 +1,294 @@
|
|||
/******************************************************
|
||||
Copyright (c) 2011-2017 Percona LLC and/or its affiliates.
|
||||
|
||||
The xbstream format writer implementation.
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; version 2 of the License.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
|
||||
|
||||
*******************************************************/
|
||||
|
||||
#include <mysql_version.h>
|
||||
#include <my_base.h>
|
||||
#include <zlib.h>
|
||||
#include "common.h"
|
||||
#include "xbstream.h"
|
||||
#include "crc_glue.h"
|
||||
|
||||
/* Group writes smaller than this into a single chunk */
|
||||
#define XB_STREAM_MIN_CHUNK_SIZE (10 * 1024 * 1024)
|
||||
|
||||
struct xb_wstream_struct {
|
||||
pthread_mutex_t mutex;
|
||||
};
|
||||
|
||||
struct xb_wstream_file_struct {
|
||||
xb_wstream_t *stream;
|
||||
char *path;
|
||||
size_t path_len;
|
||||
char chunk[XB_STREAM_MIN_CHUNK_SIZE];
|
||||
char *chunk_ptr;
|
||||
size_t chunk_free;
|
||||
my_off_t offset;
|
||||
void *userdata;
|
||||
xb_stream_write_callback *write;
|
||||
};
|
||||
|
||||
static int xb_stream_flush(xb_wstream_file_t *file);
|
||||
static int xb_stream_write_chunk(xb_wstream_file_t *file,
|
||||
const void *buf, size_t len);
|
||||
static int xb_stream_write_eof(xb_wstream_file_t *file);
|
||||
|
||||
static
|
||||
ssize_t
|
||||
xb_stream_default_write_callback(xb_wstream_file_t *file __attribute__((unused)),
|
||||
void *userdata __attribute__((unused)),
|
||||
const void *buf, size_t len)
|
||||
{
|
||||
if (my_write(my_fileno(stdout), buf, len, MYF(MY_WME | MY_NABP)))
|
||||
return -1;
|
||||
return len;
|
||||
}
|
||||
|
||||
xb_wstream_t *
|
||||
xb_stream_write_new(void)
|
||||
{
|
||||
xb_wstream_t *stream;
|
||||
|
||||
stream = (xb_wstream_t *) my_malloc(sizeof(xb_wstream_t), MYF(MY_FAE));
|
||||
pthread_mutex_init(&stream->mutex, NULL);
|
||||
|
||||
return stream;;
|
||||
}
|
||||
|
||||
xb_wstream_file_t *
|
||||
xb_stream_write_open(xb_wstream_t *stream, const char *path,
|
||||
MY_STAT *mystat __attribute__((unused)),
|
||||
void *userdata,
|
||||
xb_stream_write_callback *onwrite)
|
||||
{
|
||||
xb_wstream_file_t *file;
|
||||
size_t path_len;
|
||||
|
||||
path_len = strlen(path);
|
||||
|
||||
if (path_len > FN_REFLEN) {
|
||||
msg("xb_stream_write_open(): file path is too long.\n");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
file = (xb_wstream_file_t *) my_malloc(sizeof(xb_wstream_file_t) +
|
||||
path_len + 1, MYF(MY_FAE));
|
||||
|
||||
file->path = (char *) (file + 1);
|
||||
#ifdef _WIN32
|
||||
/* Normalize path on Windows, so we can restore elsewhere.*/
|
||||
{
|
||||
int i;
|
||||
for (i = 0; ; i++) {
|
||||
file->path[i] = (path[i] == '\\') ? '/' : path[i];
|
||||
if (!path[i])
|
||||
break;
|
||||
}
|
||||
}
|
||||
#else
|
||||
memcpy(file->path, path, path_len + 1);
|
||||
#endif
|
||||
file->path_len = path_len;
|
||||
|
||||
file->stream = stream;
|
||||
file->offset = 0;
|
||||
file->chunk_ptr = file->chunk;
|
||||
file->chunk_free = XB_STREAM_MIN_CHUNK_SIZE;
|
||||
if (onwrite) {
|
||||
#ifdef __WIN__
|
||||
setmode(fileno(stdout), _O_BINARY);
|
||||
#endif
|
||||
file->userdata = userdata;
|
||||
file->write = onwrite;
|
||||
} else {
|
||||
file->userdata = NULL;
|
||||
file->write = xb_stream_default_write_callback;
|
||||
}
|
||||
|
||||
return file;
|
||||
}
|
||||
|
||||
int
|
||||
xb_stream_write_data(xb_wstream_file_t *file, const void *buf, size_t len)
|
||||
{
|
||||
if (len < file->chunk_free) {
|
||||
memcpy(file->chunk_ptr, buf, len);
|
||||
file->chunk_ptr += len;
|
||||
file->chunk_free -= len;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (xb_stream_flush(file))
|
||||
return 1;
|
||||
|
||||
return xb_stream_write_chunk(file, buf, len);
|
||||
}
|
||||
|
||||
int
|
||||
xb_stream_write_close(xb_wstream_file_t *file)
|
||||
{
|
||||
if (xb_stream_flush(file) ||
|
||||
xb_stream_write_eof(file)) {
|
||||
my_free(file);
|
||||
return 1;
|
||||
}
|
||||
|
||||
my_free(file);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
xb_stream_write_done(xb_wstream_t *stream)
|
||||
{
|
||||
pthread_mutex_destroy(&stream->mutex);
|
||||
|
||||
my_free(stream);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static
|
||||
int
|
||||
xb_stream_flush(xb_wstream_file_t *file)
|
||||
{
|
||||
if (file->chunk_ptr == file->chunk) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (xb_stream_write_chunk(file, file->chunk,
|
||||
file->chunk_ptr - file->chunk)) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
file->chunk_ptr = file->chunk;
|
||||
file->chunk_free = XB_STREAM_MIN_CHUNK_SIZE;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static
|
||||
int
|
||||
xb_stream_write_chunk(xb_wstream_file_t *file, const void *buf, size_t len)
|
||||
{
|
||||
/* Chunk magic + flags + chunk type + path_len + path + len + offset +
|
||||
checksum */
|
||||
uchar tmpbuf[sizeof(XB_STREAM_CHUNK_MAGIC) - 1 + 1 + 1 + 4 +
|
||||
FN_REFLEN + 8 + 8 + 4];
|
||||
uchar *ptr;
|
||||
xb_wstream_t *stream = file->stream;
|
||||
ulong checksum;
|
||||
|
||||
/* Write xbstream header */
|
||||
ptr = tmpbuf;
|
||||
|
||||
/* Chunk magic */
|
||||
memcpy(ptr, XB_STREAM_CHUNK_MAGIC, sizeof(XB_STREAM_CHUNK_MAGIC) - 1);
|
||||
ptr += sizeof(XB_STREAM_CHUNK_MAGIC) - 1;
|
||||
|
||||
*ptr++ = 0; /* Chunk flags */
|
||||
|
||||
*ptr++ = (uchar) XB_CHUNK_TYPE_PAYLOAD; /* Chunk type */
|
||||
|
||||
int4store(ptr, file->path_len); /* Path length */
|
||||
ptr += 4;
|
||||
|
||||
memcpy(ptr, file->path, file->path_len); /* Path */
|
||||
ptr += file->path_len;
|
||||
|
||||
int8store(ptr, len); /* Payload length */
|
||||
ptr += 8;
|
||||
|
||||
checksum = crc32_iso3309(0, buf, (uint)len); /* checksum */
|
||||
|
||||
pthread_mutex_lock(&stream->mutex);
|
||||
|
||||
int8store(ptr, file->offset); /* Payload offset */
|
||||
ptr += 8;
|
||||
|
||||
int4store(ptr, checksum);
|
||||
ptr += 4;
|
||||
|
||||
xb_ad(ptr <= tmpbuf + sizeof(tmpbuf));
|
||||
|
||||
if (file->write(file, file->userdata, tmpbuf, ptr-tmpbuf) == -1)
|
||||
goto err;
|
||||
|
||||
|
||||
if (file->write(file, file->userdata, buf, len) == -1) /* Payload */
|
||||
goto err;
|
||||
|
||||
file->offset+= len;
|
||||
|
||||
pthread_mutex_unlock(&stream->mutex);
|
||||
|
||||
return 0;
|
||||
|
||||
err:
|
||||
|
||||
pthread_mutex_unlock(&stream->mutex);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static
|
||||
int
|
||||
xb_stream_write_eof(xb_wstream_file_t *file)
|
||||
{
|
||||
/* Chunk magic + flags + chunk type + path_len + path */
|
||||
uchar tmpbuf[sizeof(XB_STREAM_CHUNK_MAGIC) - 1 + 1 + 1 + 4 +
|
||||
FN_REFLEN];
|
||||
uchar *ptr;
|
||||
xb_wstream_t *stream = file->stream;
|
||||
|
||||
pthread_mutex_lock(&stream->mutex);
|
||||
|
||||
/* Write xbstream header */
|
||||
ptr = tmpbuf;
|
||||
|
||||
/* Chunk magic */
|
||||
memcpy(ptr, XB_STREAM_CHUNK_MAGIC, sizeof(XB_STREAM_CHUNK_MAGIC) - 1);
|
||||
ptr += sizeof(XB_STREAM_CHUNK_MAGIC) - 1;
|
||||
|
||||
*ptr++ = 0; /* Chunk flags */
|
||||
|
||||
*ptr++ = (uchar) XB_CHUNK_TYPE_EOF; /* Chunk type */
|
||||
|
||||
int4store(ptr, file->path_len); /* Path length */
|
||||
ptr += 4;
|
||||
|
||||
memcpy(ptr, file->path, file->path_len); /* Path */
|
||||
ptr += file->path_len;
|
||||
|
||||
xb_ad(ptr <= tmpbuf + sizeof(tmpbuf));
|
||||
|
||||
if (file->write(file, file->userdata, tmpbuf,
|
||||
(ulonglong) (ptr - tmpbuf)) == -1)
|
||||
goto err;
|
||||
|
||||
pthread_mutex_unlock(&stream->mutex);
|
||||
|
||||
return 0;
|
||||
err:
|
||||
|
||||
pthread_mutex_unlock(&stream->mutex);
|
||||
|
||||
return 1;
|
||||
}
|
7498
extra/mariabackup/xtrabackup.cc
Normal file
7498
extra/mariabackup/xtrabackup.cc
Normal file
File diff suppressed because it is too large
Load diff
247
extra/mariabackup/xtrabackup.h
Normal file
247
extra/mariabackup/xtrabackup.h
Normal file
|
@ -0,0 +1,247 @@
|
|||
/******************************************************
|
||||
Copyright (c) 2011-2015 Percona LLC and/or its affiliates.
|
||||
|
||||
Declarations for xtrabackup.cc
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; version 2 of the License.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
|
||||
|
||||
*******************************************************/
|
||||
|
||||
#ifndef XB_XTRABACKUP_H
|
||||
#define XB_XTRABACKUP_H
|
||||
|
||||
#include <my_getopt.h>
|
||||
#include "datasink.h"
|
||||
#include "xbstream.h"
|
||||
#include "changed_page_bitmap.h"
|
||||
|
||||
#ifdef __WIN__
|
||||
#define XB_FILE_UNDEFINED NULL
|
||||
#else
|
||||
#define XB_FILE_UNDEFINED (-1)
|
||||
#endif
|
||||
|
||||
typedef struct {
|
||||
ulint page_size;
|
||||
ulint zip_size;
|
||||
ulint space_id;
|
||||
} xb_delta_info_t;
|
||||
|
||||
/* ======== Datafiles iterator ======== */
|
||||
typedef struct {
|
||||
fil_system_t *system;
|
||||
fil_space_t *space;
|
||||
fil_node_t *node;
|
||||
ibool started;
|
||||
os_ib_mutex_t mutex;
|
||||
} datafiles_iter_t;
|
||||
|
||||
/* value of the --incremental option */
|
||||
extern lsn_t incremental_lsn;
|
||||
|
||||
extern char *xtrabackup_target_dir;
|
||||
extern char *xtrabackup_incremental_dir;
|
||||
extern char *xtrabackup_incremental_basedir;
|
||||
extern char *innobase_data_home_dir;
|
||||
extern char *innobase_buffer_pool_filename;
|
||||
extern ds_ctxt_t *ds_meta;
|
||||
extern ds_ctxt_t *ds_data;
|
||||
|
||||
/* The last checkpoint LSN at the backup startup time */
|
||||
extern lsn_t checkpoint_lsn_start;
|
||||
|
||||
extern xb_page_bitmap *changed_page_bitmap;
|
||||
|
||||
extern char *xtrabackup_incremental;
|
||||
extern my_bool xtrabackup_incremental_force_scan;
|
||||
|
||||
extern lsn_t metadata_from_lsn;
|
||||
extern lsn_t metadata_to_lsn;
|
||||
extern lsn_t metadata_last_lsn;
|
||||
|
||||
extern xb_stream_fmt_t xtrabackup_stream_fmt;
|
||||
extern ibool xtrabackup_stream;
|
||||
|
||||
extern char *xtrabackup_tables;
|
||||
extern char *xtrabackup_tables_file;
|
||||
extern char *xtrabackup_databases;
|
||||
extern char *xtrabackup_databases_file;
|
||||
extern char *xtrabackup_tables_exclude;
|
||||
extern char *xtrabackup_databases_exclude;
|
||||
|
||||
extern ibool xtrabackup_compress;
|
||||
extern ibool xtrabackup_encrypt;
|
||||
|
||||
extern my_bool xtrabackup_backup;
|
||||
extern my_bool xtrabackup_prepare;
|
||||
extern my_bool xtrabackup_apply_log_only;
|
||||
extern my_bool xtrabackup_copy_back;
|
||||
extern my_bool xtrabackup_move_back;
|
||||
extern my_bool xtrabackup_decrypt_decompress;
|
||||
|
||||
extern char *innobase_data_file_path;
|
||||
extern char *innobase_doublewrite_file;
|
||||
extern char *xtrabackup_encrypt_key;
|
||||
extern char *xtrabackup_encrypt_key_file;
|
||||
extern longlong innobase_log_file_size;
|
||||
extern long innobase_log_files_in_group;
|
||||
extern longlong innobase_page_size;
|
||||
|
||||
extern const char *xtrabackup_encrypt_algo_names[];
|
||||
extern TYPELIB xtrabackup_encrypt_algo_typelib;
|
||||
|
||||
extern int xtrabackup_parallel;
|
||||
|
||||
extern my_bool xb_close_files;
|
||||
extern const char *xtrabackup_compress_alg;
|
||||
#ifdef __cplusplus
|
||||
extern "C"{
|
||||
#endif
|
||||
extern uint xtrabackup_compress_threads;
|
||||
extern ulonglong xtrabackup_compress_chunk_size;
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
extern ulong xtrabackup_encrypt_algo;
|
||||
extern uint xtrabackup_encrypt_threads;
|
||||
extern ulonglong xtrabackup_encrypt_chunk_size;
|
||||
extern my_bool xtrabackup_export;
|
||||
extern char *xtrabackup_incremental_basedir;
|
||||
extern char *xtrabackup_extra_lsndir;
|
||||
extern char *xtrabackup_incremental_dir;
|
||||
extern ulint xtrabackup_log_copy_interval;
|
||||
extern char *xtrabackup_stream_str;
|
||||
extern long xtrabackup_throttle;
|
||||
extern longlong xtrabackup_use_memory;
|
||||
|
||||
extern my_bool opt_galera_info;
|
||||
extern my_bool opt_slave_info;
|
||||
extern my_bool opt_no_lock;
|
||||
extern my_bool opt_safe_slave_backup;
|
||||
extern my_bool opt_rsync;
|
||||
extern my_bool opt_force_non_empty_dirs;
|
||||
extern my_bool opt_noversioncheck;
|
||||
extern my_bool opt_no_backup_locks;
|
||||
extern my_bool opt_decompress;
|
||||
extern my_bool opt_remove_original;
|
||||
|
||||
extern char *opt_incremental_history_name;
|
||||
extern char *opt_incremental_history_uuid;
|
||||
|
||||
extern char *opt_user;
|
||||
extern char *opt_password;
|
||||
extern char *opt_host;
|
||||
extern char *opt_defaults_group;
|
||||
extern char *opt_socket;
|
||||
extern uint opt_port;
|
||||
extern char *opt_login_path;
|
||||
extern char *opt_log_bin;
|
||||
|
||||
extern const char *query_type_names[];
|
||||
|
||||
enum query_type_t {QUERY_TYPE_ALL, QUERY_TYPE_UPDATE,
|
||||
QUERY_TYPE_SELECT};
|
||||
|
||||
extern TYPELIB query_type_typelib;
|
||||
|
||||
extern ulong opt_lock_wait_query_type;
|
||||
extern ulong opt_kill_long_query_type;
|
||||
|
||||
extern ulong opt_decrypt_algo;
|
||||
|
||||
extern uint opt_kill_long_queries_timeout;
|
||||
extern uint opt_lock_wait_timeout;
|
||||
extern uint opt_lock_wait_threshold;
|
||||
extern uint opt_debug_sleep_before_unlock;
|
||||
extern uint opt_safe_slave_backup_timeout;
|
||||
|
||||
extern const char *opt_history;
|
||||
extern my_bool opt_decrypt;
|
||||
|
||||
enum binlog_info_enum { BINLOG_INFO_OFF, BINLOG_INFO_LOCKLESS, BINLOG_INFO_ON,
|
||||
BINLOG_INFO_AUTO};
|
||||
|
||||
extern ulong opt_binlog_info;
|
||||
|
||||
void xtrabackup_io_throttling(void);
|
||||
my_bool xb_write_delta_metadata(const char *filename,
|
||||
const xb_delta_info_t *info);
|
||||
|
||||
datafiles_iter_t *datafiles_iter_new(fil_system_t *f_system);
|
||||
fil_node_t *datafiles_iter_next(datafiles_iter_t *it);
|
||||
void datafiles_iter_free(datafiles_iter_t *it);
|
||||
|
||||
/************************************************************************
|
||||
Initialize the tablespace memory cache and populate it by scanning for and
|
||||
opening data files */
|
||||
ulint xb_data_files_init(void);
|
||||
|
||||
/************************************************************************
|
||||
Destroy the tablespace memory cache. */
|
||||
void xb_data_files_close(void);
|
||||
|
||||
/***********************************************************************
|
||||
Reads the space flags from a given data file and returns the compressed
|
||||
page size, or 0 if the space is not compressed. */
|
||||
ulint xb_get_zip_size(os_file_t file);
|
||||
|
||||
/************************************************************************
|
||||
Checks if a table specified as a name in the form "database/name" (InnoDB 5.6)
|
||||
or "./database/name.ibd" (InnoDB 5.5-) should be skipped from backup based on
|
||||
the --tables or --tables-file options.
|
||||
|
||||
@return TRUE if the table should be skipped. */
|
||||
my_bool
|
||||
check_if_skip_table(
|
||||
/******************/
|
||||
const char* name); /*!< in: path to the table */
|
||||
|
||||
|
||||
/************************************************************************
|
||||
Checks if a database specified by path should be skipped from backup based on
|
||||
the --databases, --databases_file or --databases_exclude options.
|
||||
|
||||
@return TRUE if the table should be skipped. */
|
||||
my_bool
|
||||
check_if_skip_database_by_path(
|
||||
const char* path /*!< in: path to the db directory. */
|
||||
);
|
||||
|
||||
/************************************************************************
|
||||
Check if parameter is set in defaults file or via command line argument
|
||||
@return true if parameter is set. */
|
||||
bool
|
||||
check_if_param_set(const char *param);
|
||||
|
||||
#if defined(HAVE_OPENSSL)
|
||||
extern my_bool opt_use_ssl;
|
||||
extern my_bool opt_ssl_verify_server_cert;
|
||||
#if !defined(HAVE_YASSL)
|
||||
extern char *opt_server_public_key;
|
||||
#endif
|
||||
#endif
|
||||
|
||||
|
||||
void
|
||||
xtrabackup_backup_func(void);
|
||||
|
||||
my_bool
|
||||
xb_get_one_option(int optid,
|
||||
const struct my_option *opt __attribute__((unused)),
|
||||
char *argument);
|
||||
|
||||
const char*
|
||||
xb_get_copy_action(const char *dflt = "Copying");
|
||||
|
||||
#endif /* XB_XTRABACKUP_H */
|
|
@ -18,74 +18,7 @@
|
|||
#ifndef MY_CRYPT_INCLUDED
|
||||
#define MY_CRYPT_INCLUDED
|
||||
|
||||
#include <my_global.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/* return values from my_aes_encrypt/my_aes_decrypt functions */
|
||||
#define MY_AES_OK 0
|
||||
#define MY_AES_BAD_DATA -100
|
||||
#define MY_AES_OPENSSL_ERROR -101
|
||||
#define MY_AES_BAD_KEYSIZE -102
|
||||
|
||||
/* The block size for all supported algorithms */
|
||||
#define MY_AES_BLOCK_SIZE 16
|
||||
|
||||
/* The max key length of all supported algorithms */
|
||||
#define MY_AES_MAX_KEY_LENGTH 32
|
||||
|
||||
#define MY_AES_CTX_SIZE 512
|
||||
|
||||
enum my_aes_mode {
|
||||
MY_AES_ECB, MY_AES_CBC
|
||||
#ifdef HAVE_EncryptAes128Ctr
|
||||
, MY_AES_CTR
|
||||
#endif
|
||||
#ifdef HAVE_EncryptAes128Gcm
|
||||
, MY_AES_GCM
|
||||
#endif
|
||||
};
|
||||
|
||||
int my_aes_crypt_init(void *ctx, enum my_aes_mode mode, int flags,
|
||||
const unsigned char* key, unsigned int klen,
|
||||
const unsigned char* iv, unsigned int ivlen);
|
||||
int my_aes_crypt_update(void *ctx, const uchar *src, uint slen,
|
||||
uchar *dst, uint *dlen);
|
||||
int my_aes_crypt_finish(void *ctx, uchar *dst, uint *dlen);
|
||||
int my_aes_crypt(enum my_aes_mode mode, int flags,
|
||||
const uchar *src, uint slen, uchar *dst, uint *dlen,
|
||||
const uchar *key, uint klen, const uchar *iv, uint ivlen);
|
||||
|
||||
/*
|
||||
calculate the length of the cyphertext from the length of the plaintext
|
||||
for different AES encryption modes with padding enabled.
|
||||
Without padding (ENCRYPTION_FLAG_NOPAD) cyphertext has the same length
|
||||
as the plaintext
|
||||
*/
|
||||
static inline uint my_aes_get_size(enum my_aes_mode mode __attribute__((unused)), uint source_length)
|
||||
{
|
||||
#ifdef HAVE_EncryptAes128Ctr
|
||||
if (mode == MY_AES_CTR)
|
||||
return source_length;
|
||||
#ifdef HAVE_EncryptAes128Gcm
|
||||
if (mode == MY_AES_GCM)
|
||||
return source_length + MY_AES_BLOCK_SIZE;
|
||||
#endif
|
||||
#endif
|
||||
return (source_length / MY_AES_BLOCK_SIZE + 1) * MY_AES_BLOCK_SIZE;
|
||||
}
|
||||
|
||||
static inline uint my_aes_ctx_size(enum my_aes_mode mode __attribute__((unused)))
|
||||
{
|
||||
return MY_AES_CTX_SIZE;
|
||||
}
|
||||
|
||||
int my_random_bytes(uchar* buf, int num);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
#include <my_config.h> /* HAVE_EncryptAes128{Ctr,Gcm} */
|
||||
#include <mysql/service_my_crypt.h>
|
||||
|
||||
#endif /* MY_CRYPT_INCLUDED */
|
||||
|
|
|
@ -346,6 +346,26 @@ int my_pthread_mutex_trylock(pthread_mutex_t *mutex);
|
|||
} while(0)
|
||||
#endif /* !set_timespec_time_nsec */
|
||||
|
||||
#ifdef MYSQL_CLIENT
|
||||
#define _current_thd() NULL
|
||||
#elif defined(_WIN32)
|
||||
#ifdef __cplusplus
|
||||
extern "C"
|
||||
#endif
|
||||
MYSQL_THD _current_thd_noinline();
|
||||
#define _current_thd() _current_thd_noinline()
|
||||
#else
|
||||
/*
|
||||
THR_THD is a key which will be used to set/get THD* for a thread,
|
||||
using my_pthread_setspecific_ptr()/my_thread_getspecific_ptr().
|
||||
*/
|
||||
extern pthread_key(MYSQL_THD, THR_THD);
|
||||
static inline MYSQL_THD _current_thd(void)
|
||||
{
|
||||
return my_pthread_getspecific_ptr(MYSQL_THD,THR_THD);
|
||||
}
|
||||
#endif
|
||||
|
||||
/* safe_mutex adds checking to mutex for easier debugging */
|
||||
struct st_hash;
|
||||
typedef struct st_safe_mutex_t
|
||||
|
|
|
@ -42,6 +42,7 @@ typedef struct my_aio_result {
|
|||
#include <malloc.h> /*for alloca*/
|
||||
#endif
|
||||
#include <mysql/plugin.h>
|
||||
#include <mysql/service_my_print_error.h>
|
||||
|
||||
#define MY_INIT(name) { my_progname= name; my_init(); }
|
||||
|
||||
|
@ -104,18 +105,10 @@ typedef struct my_aio_result {
|
|||
#define MY_GIVE_INFO 2U /* Give time info about process*/
|
||||
#define MY_DONT_FREE_DBUG 4U /* Do not call DBUG_END() in my_end() */
|
||||
|
||||
#define ME_HIGHBYTE 8U /* Shift for colours */
|
||||
#define ME_NOCUR 1U /* Don't use curses message */
|
||||
#define ME_OLDWIN 2U /* Use old window */
|
||||
#define ME_BELL 4U /* Ring bell then printing message */
|
||||
#define ME_HOLDTANG 8U /* Don't delete last keys */
|
||||
#define ME_WAITTOT 16U /* Wait for errtime secs of for a action */
|
||||
#define ME_WAITTANG 32U /* Wait for a user action */
|
||||
#define ME_NOREFRESH 64U /* Write the error message to error log */
|
||||
#define ME_NOINPUT 128U /* Dont use the input libary */
|
||||
#define ME_COLOUR1 ((1U << ME_HIGHBYTE)) /* Possibly error-colours */
|
||||
#define ME_COLOUR2 ((2U << ME_HIGHBYTE))
|
||||
#define ME_COLOUR3 ((3U << ME_HIGHBYTE))
|
||||
#define ME_BELL 4U /* Ring bell then printing message */
|
||||
#define ME_WAITTANG 0 /* Wait for a user action */
|
||||
#define ME_NOREFRESH 64U /* Write the error message to error log */
|
||||
#define ME_NOINPUT 0 /* Dont use the input libary */
|
||||
#define ME_JUST_INFO 1024U /**< not error but just info */
|
||||
#define ME_JUST_WARNING 2048U /**< not error but just warning */
|
||||
#define ME_FATALERROR 4096U /* Fatal statement error */
|
||||
|
@ -725,12 +718,6 @@ extern int my_sync(File fd, myf my_flags);
|
|||
extern int my_sync_dir(const char *dir_name, myf my_flags);
|
||||
extern int my_sync_dir_by_file(const char *file_name, myf my_flags);
|
||||
extern const char *my_get_err_msg(uint nr);
|
||||
extern void my_error(uint nr,myf MyFlags, ...);
|
||||
extern void my_printf_error(uint my_err, const char *format,
|
||||
myf MyFlags, ...)
|
||||
ATTRIBUTE_FORMAT(printf, 2, 4);
|
||||
extern void my_printv_error(uint error, const char *format, myf MyFlags,
|
||||
va_list ap);
|
||||
extern int my_error_register(const char** (*get_errmsgs) (int nr),
|
||||
uint first, uint last);
|
||||
extern my_bool my_error_unregister(uint first, uint last);
|
||||
|
|
|
@ -75,7 +75,7 @@ typedef struct st_mysql_xid MYSQL_XID;
|
|||
#define MYSQL_PLUGIN_INTERFACE_VERSION 0x0104
|
||||
|
||||
/* MariaDB plugin interface version */
|
||||
#define MARIA_PLUGIN_INTERFACE_VERSION 0x010c
|
||||
#define MARIA_PLUGIN_INTERFACE_VERSION 0x010d
|
||||
|
||||
/*
|
||||
The allowable types of plugins
|
||||
|
|
|
@ -137,6 +137,43 @@ size_t my_md5_context_size();
|
|||
void my_md5_init(void *context);
|
||||
void my_md5_input(void *context, const unsigned char *buf, size_t len);
|
||||
void my_md5_result(void *context, unsigned char *digest);
|
||||
enum my_aes_mode {
|
||||
MY_AES_ECB, MY_AES_CBC
|
||||
};
|
||||
extern struct my_crypt_service_st {
|
||||
int (*my_aes_crypt_init)(void *ctx, enum my_aes_mode mode, int flags,
|
||||
const unsigned char* key, unsigned int klen,
|
||||
const unsigned char* iv, unsigned int ivlen);
|
||||
int (*my_aes_crypt_update)(void *ctx, const unsigned char *src, unsigned int slen,
|
||||
unsigned char *dst, unsigned int *dlen);
|
||||
int (*my_aes_crypt_finish)(void *ctx, unsigned char *dst, unsigned int *dlen);
|
||||
int (*my_aes_crypt)(enum my_aes_mode mode, int flags,
|
||||
const unsigned char *src, unsigned int slen, unsigned char *dst, unsigned int *dlen,
|
||||
const unsigned char *key, unsigned int klen, const unsigned char *iv, unsigned int ivlen);
|
||||
unsigned int (*my_aes_get_size)(enum my_aes_mode mode, unsigned int source_length);
|
||||
unsigned int (*my_aes_ctx_size)(enum my_aes_mode mode);
|
||||
int (*my_random_bytes)(unsigned char* buf, int num);
|
||||
} *my_crypt_service;
|
||||
int my_aes_crypt_init(void *ctx, enum my_aes_mode mode, int flags,
|
||||
const unsigned char* key, unsigned int klen,
|
||||
const unsigned char* iv, unsigned int ivlen);
|
||||
int my_aes_crypt_update(void *ctx, const unsigned char *src, unsigned int slen,
|
||||
unsigned char *dst, unsigned int *dlen);
|
||||
int my_aes_crypt_finish(void *ctx, unsigned char *dst, unsigned int *dlen);
|
||||
int my_aes_crypt(enum my_aes_mode mode, int flags,
|
||||
const unsigned char *src, unsigned int slen, unsigned char *dst, unsigned int *dlen,
|
||||
const unsigned char *key, unsigned int klen, const unsigned char *iv, unsigned int ivlen);
|
||||
int my_random_bytes(unsigned char* buf, int num);
|
||||
unsigned int my_aes_get_size(enum my_aes_mode mode, unsigned int source_length);
|
||||
unsigned int my_aes_ctx_size(enum my_aes_mode mode);
|
||||
extern struct my_print_error_service_st {
|
||||
void(*my_error_func)(unsigned int nr, unsigned long MyFlags, ...);
|
||||
void(*my_printf_error_func)(unsigned int nr, const char *fmt, unsigned long MyFlags,...);
|
||||
void(*my_printv_error_func)(unsigned int error, const char *format, unsigned long MyFlags, va_list ap);
|
||||
} *my_print_error_service;
|
||||
extern void my_error(unsigned int nr, unsigned long MyFlags, ...);
|
||||
extern void my_printf_error(unsigned int my_err, const char *format, unsigned long MyFlags, ...);
|
||||
extern void my_printv_error(unsigned int error, const char *format, unsigned long MyFlags,va_list ap);
|
||||
extern struct my_snprintf_service_st {
|
||||
size_t (*my_snprintf_type)(char*, size_t, const char*, ...);
|
||||
size_t (*my_vsnprintf_type)(char *, size_t, const char*, va_list);
|
||||
|
|
|
@ -137,6 +137,43 @@ size_t my_md5_context_size();
|
|||
void my_md5_init(void *context);
|
||||
void my_md5_input(void *context, const unsigned char *buf, size_t len);
|
||||
void my_md5_result(void *context, unsigned char *digest);
|
||||
enum my_aes_mode {
|
||||
MY_AES_ECB, MY_AES_CBC
|
||||
};
|
||||
extern struct my_crypt_service_st {
|
||||
int (*my_aes_crypt_init)(void *ctx, enum my_aes_mode mode, int flags,
|
||||
const unsigned char* key, unsigned int klen,
|
||||
const unsigned char* iv, unsigned int ivlen);
|
||||
int (*my_aes_crypt_update)(void *ctx, const unsigned char *src, unsigned int slen,
|
||||
unsigned char *dst, unsigned int *dlen);
|
||||
int (*my_aes_crypt_finish)(void *ctx, unsigned char *dst, unsigned int *dlen);
|
||||
int (*my_aes_crypt)(enum my_aes_mode mode, int flags,
|
||||
const unsigned char *src, unsigned int slen, unsigned char *dst, unsigned int *dlen,
|
||||
const unsigned char *key, unsigned int klen, const unsigned char *iv, unsigned int ivlen);
|
||||
unsigned int (*my_aes_get_size)(enum my_aes_mode mode, unsigned int source_length);
|
||||
unsigned int (*my_aes_ctx_size)(enum my_aes_mode mode);
|
||||
int (*my_random_bytes)(unsigned char* buf, int num);
|
||||
} *my_crypt_service;
|
||||
int my_aes_crypt_init(void *ctx, enum my_aes_mode mode, int flags,
|
||||
const unsigned char* key, unsigned int klen,
|
||||
const unsigned char* iv, unsigned int ivlen);
|
||||
int my_aes_crypt_update(void *ctx, const unsigned char *src, unsigned int slen,
|
||||
unsigned char *dst, unsigned int *dlen);
|
||||
int my_aes_crypt_finish(void *ctx, unsigned char *dst, unsigned int *dlen);
|
||||
int my_aes_crypt(enum my_aes_mode mode, int flags,
|
||||
const unsigned char *src, unsigned int slen, unsigned char *dst, unsigned int *dlen,
|
||||
const unsigned char *key, unsigned int klen, const unsigned char *iv, unsigned int ivlen);
|
||||
int my_random_bytes(unsigned char* buf, int num);
|
||||
unsigned int my_aes_get_size(enum my_aes_mode mode, unsigned int source_length);
|
||||
unsigned int my_aes_ctx_size(enum my_aes_mode mode);
|
||||
extern struct my_print_error_service_st {
|
||||
void(*my_error_func)(unsigned int nr, unsigned long MyFlags, ...);
|
||||
void(*my_printf_error_func)(unsigned int nr, const char *fmt, unsigned long MyFlags,...);
|
||||
void(*my_printv_error_func)(unsigned int error, const char *format, unsigned long MyFlags, va_list ap);
|
||||
} *my_print_error_service;
|
||||
extern void my_error(unsigned int nr, unsigned long MyFlags, ...);
|
||||
extern void my_printf_error(unsigned int my_err, const char *format, unsigned long MyFlags, ...);
|
||||
extern void my_printv_error(unsigned int error, const char *format, unsigned long MyFlags,va_list ap);
|
||||
extern struct my_snprintf_service_st {
|
||||
size_t (*my_snprintf_type)(char*, size_t, const char*, ...);
|
||||
size_t (*my_vsnprintf_type)(char *, size_t, const char*, va_list);
|
||||
|
|
|
@ -137,6 +137,43 @@ size_t my_md5_context_size();
|
|||
void my_md5_init(void *context);
|
||||
void my_md5_input(void *context, const unsigned char *buf, size_t len);
|
||||
void my_md5_result(void *context, unsigned char *digest);
|
||||
enum my_aes_mode {
|
||||
MY_AES_ECB, MY_AES_CBC
|
||||
};
|
||||
extern struct my_crypt_service_st {
|
||||
int (*my_aes_crypt_init)(void *ctx, enum my_aes_mode mode, int flags,
|
||||
const unsigned char* key, unsigned int klen,
|
||||
const unsigned char* iv, unsigned int ivlen);
|
||||
int (*my_aes_crypt_update)(void *ctx, const unsigned char *src, unsigned int slen,
|
||||
unsigned char *dst, unsigned int *dlen);
|
||||
int (*my_aes_crypt_finish)(void *ctx, unsigned char *dst, unsigned int *dlen);
|
||||
int (*my_aes_crypt)(enum my_aes_mode mode, int flags,
|
||||
const unsigned char *src, unsigned int slen, unsigned char *dst, unsigned int *dlen,
|
||||
const unsigned char *key, unsigned int klen, const unsigned char *iv, unsigned int ivlen);
|
||||
unsigned int (*my_aes_get_size)(enum my_aes_mode mode, unsigned int source_length);
|
||||
unsigned int (*my_aes_ctx_size)(enum my_aes_mode mode);
|
||||
int (*my_random_bytes)(unsigned char* buf, int num);
|
||||
} *my_crypt_service;
|
||||
int my_aes_crypt_init(void *ctx, enum my_aes_mode mode, int flags,
|
||||
const unsigned char* key, unsigned int klen,
|
||||
const unsigned char* iv, unsigned int ivlen);
|
||||
int my_aes_crypt_update(void *ctx, const unsigned char *src, unsigned int slen,
|
||||
unsigned char *dst, unsigned int *dlen);
|
||||
int my_aes_crypt_finish(void *ctx, unsigned char *dst, unsigned int *dlen);
|
||||
int my_aes_crypt(enum my_aes_mode mode, int flags,
|
||||
const unsigned char *src, unsigned int slen, unsigned char *dst, unsigned int *dlen,
|
||||
const unsigned char *key, unsigned int klen, const unsigned char *iv, unsigned int ivlen);
|
||||
int my_random_bytes(unsigned char* buf, int num);
|
||||
unsigned int my_aes_get_size(enum my_aes_mode mode, unsigned int source_length);
|
||||
unsigned int my_aes_ctx_size(enum my_aes_mode mode);
|
||||
extern struct my_print_error_service_st {
|
||||
void(*my_error_func)(unsigned int nr, unsigned long MyFlags, ...);
|
||||
void(*my_printf_error_func)(unsigned int nr, const char *fmt, unsigned long MyFlags,...);
|
||||
void(*my_printv_error_func)(unsigned int error, const char *format, unsigned long MyFlags, va_list ap);
|
||||
} *my_print_error_service;
|
||||
extern void my_error(unsigned int nr, unsigned long MyFlags, ...);
|
||||
extern void my_printf_error(unsigned int my_err, const char *format, unsigned long MyFlags, ...);
|
||||
extern void my_printv_error(unsigned int error, const char *format, unsigned long MyFlags,va_list ap);
|
||||
extern struct my_snprintf_service_st {
|
||||
size_t (*my_snprintf_type)(char*, size_t, const char*, ...);
|
||||
size_t (*my_vsnprintf_type)(char *, size_t, const char*, va_list);
|
||||
|
|
|
@ -137,6 +137,43 @@ size_t my_md5_context_size();
|
|||
void my_md5_init(void *context);
|
||||
void my_md5_input(void *context, const unsigned char *buf, size_t len);
|
||||
void my_md5_result(void *context, unsigned char *digest);
|
||||
enum my_aes_mode {
|
||||
MY_AES_ECB, MY_AES_CBC
|
||||
};
|
||||
extern struct my_crypt_service_st {
|
||||
int (*my_aes_crypt_init)(void *ctx, enum my_aes_mode mode, int flags,
|
||||
const unsigned char* key, unsigned int klen,
|
||||
const unsigned char* iv, unsigned int ivlen);
|
||||
int (*my_aes_crypt_update)(void *ctx, const unsigned char *src, unsigned int slen,
|
||||
unsigned char *dst, unsigned int *dlen);
|
||||
int (*my_aes_crypt_finish)(void *ctx, unsigned char *dst, unsigned int *dlen);
|
||||
int (*my_aes_crypt)(enum my_aes_mode mode, int flags,
|
||||
const unsigned char *src, unsigned int slen, unsigned char *dst, unsigned int *dlen,
|
||||
const unsigned char *key, unsigned int klen, const unsigned char *iv, unsigned int ivlen);
|
||||
unsigned int (*my_aes_get_size)(enum my_aes_mode mode, unsigned int source_length);
|
||||
unsigned int (*my_aes_ctx_size)(enum my_aes_mode mode);
|
||||
int (*my_random_bytes)(unsigned char* buf, int num);
|
||||
} *my_crypt_service;
|
||||
int my_aes_crypt_init(void *ctx, enum my_aes_mode mode, int flags,
|
||||
const unsigned char* key, unsigned int klen,
|
||||
const unsigned char* iv, unsigned int ivlen);
|
||||
int my_aes_crypt_update(void *ctx, const unsigned char *src, unsigned int slen,
|
||||
unsigned char *dst, unsigned int *dlen);
|
||||
int my_aes_crypt_finish(void *ctx, unsigned char *dst, unsigned int *dlen);
|
||||
int my_aes_crypt(enum my_aes_mode mode, int flags,
|
||||
const unsigned char *src, unsigned int slen, unsigned char *dst, unsigned int *dlen,
|
||||
const unsigned char *key, unsigned int klen, const unsigned char *iv, unsigned int ivlen);
|
||||
int my_random_bytes(unsigned char* buf, int num);
|
||||
unsigned int my_aes_get_size(enum my_aes_mode mode, unsigned int source_length);
|
||||
unsigned int my_aes_ctx_size(enum my_aes_mode mode);
|
||||
extern struct my_print_error_service_st {
|
||||
void(*my_error_func)(unsigned int nr, unsigned long MyFlags, ...);
|
||||
void(*my_printf_error_func)(unsigned int nr, const char *fmt, unsigned long MyFlags,...);
|
||||
void(*my_printv_error_func)(unsigned int error, const char *format, unsigned long MyFlags, va_list ap);
|
||||
} *my_print_error_service;
|
||||
extern void my_error(unsigned int nr, unsigned long MyFlags, ...);
|
||||
extern void my_printf_error(unsigned int my_err, const char *format, unsigned long MyFlags, ...);
|
||||
extern void my_printv_error(unsigned int error, const char *format, unsigned long MyFlags,va_list ap);
|
||||
extern struct my_snprintf_service_st {
|
||||
size_t (*my_snprintf_type)(char*, size_t, const char*, ...);
|
||||
size_t (*my_vsnprintf_type)(char *, size_t, const char*, va_list);
|
||||
|
|
|
@ -137,6 +137,43 @@ size_t my_md5_context_size();
|
|||
void my_md5_init(void *context);
|
||||
void my_md5_input(void *context, const unsigned char *buf, size_t len);
|
||||
void my_md5_result(void *context, unsigned char *digest);
|
||||
enum my_aes_mode {
|
||||
MY_AES_ECB, MY_AES_CBC
|
||||
};
|
||||
extern struct my_crypt_service_st {
|
||||
int (*my_aes_crypt_init)(void *ctx, enum my_aes_mode mode, int flags,
|
||||
const unsigned char* key, unsigned int klen,
|
||||
const unsigned char* iv, unsigned int ivlen);
|
||||
int (*my_aes_crypt_update)(void *ctx, const unsigned char *src, unsigned int slen,
|
||||
unsigned char *dst, unsigned int *dlen);
|
||||
int (*my_aes_crypt_finish)(void *ctx, unsigned char *dst, unsigned int *dlen);
|
||||
int (*my_aes_crypt)(enum my_aes_mode mode, int flags,
|
||||
const unsigned char *src, unsigned int slen, unsigned char *dst, unsigned int *dlen,
|
||||
const unsigned char *key, unsigned int klen, const unsigned char *iv, unsigned int ivlen);
|
||||
unsigned int (*my_aes_get_size)(enum my_aes_mode mode, unsigned int source_length);
|
||||
unsigned int (*my_aes_ctx_size)(enum my_aes_mode mode);
|
||||
int (*my_random_bytes)(unsigned char* buf, int num);
|
||||
} *my_crypt_service;
|
||||
int my_aes_crypt_init(void *ctx, enum my_aes_mode mode, int flags,
|
||||
const unsigned char* key, unsigned int klen,
|
||||
const unsigned char* iv, unsigned int ivlen);
|
||||
int my_aes_crypt_update(void *ctx, const unsigned char *src, unsigned int slen,
|
||||
unsigned char *dst, unsigned int *dlen);
|
||||
int my_aes_crypt_finish(void *ctx, unsigned char *dst, unsigned int *dlen);
|
||||
int my_aes_crypt(enum my_aes_mode mode, int flags,
|
||||
const unsigned char *src, unsigned int slen, unsigned char *dst, unsigned int *dlen,
|
||||
const unsigned char *key, unsigned int klen, const unsigned char *iv, unsigned int ivlen);
|
||||
int my_random_bytes(unsigned char* buf, int num);
|
||||
unsigned int my_aes_get_size(enum my_aes_mode mode, unsigned int source_length);
|
||||
unsigned int my_aes_ctx_size(enum my_aes_mode mode);
|
||||
extern struct my_print_error_service_st {
|
||||
void(*my_error_func)(unsigned int nr, unsigned long MyFlags, ...);
|
||||
void(*my_printf_error_func)(unsigned int nr, const char *fmt, unsigned long MyFlags,...);
|
||||
void(*my_printv_error_func)(unsigned int error, const char *format, unsigned long MyFlags, va_list ap);
|
||||
} *my_print_error_service;
|
||||
extern void my_error(unsigned int nr, unsigned long MyFlags, ...);
|
||||
extern void my_printf_error(unsigned int my_err, const char *format, unsigned long MyFlags, ...);
|
||||
extern void my_printv_error(unsigned int error, const char *format, unsigned long MyFlags,va_list ap);
|
||||
extern struct my_snprintf_service_st {
|
||||
size_t (*my_snprintf_type)(char*, size_t, const char*, ...);
|
||||
size_t (*my_vsnprintf_type)(char *, size_t, const char*, va_list);
|
||||
|
|
120
include/mysql/service_my_crypt.h
Normal file
120
include/mysql/service_my_crypt.h
Normal file
|
@ -0,0 +1,120 @@
|
|||
#ifndef MYSQL_SERVICE_MY_CRYPT_INCLUDED
|
||||
#define MYSQL_SERVICE_MY_CRYPT_INCLUDED
|
||||
|
||||
/*
|
||||
Copyright (c) 2014 Google Inc.
|
||||
Copyright (c) 2014, 2015 MariaDB Corporation
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; version 2 of the License.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */
|
||||
|
||||
/**
|
||||
@file
|
||||
my crypt service
|
||||
|
||||
AES encryption functions, and a function to generate random bytes.
|
||||
|
||||
Include my_config.h before this file to use CTR and GCM modes
|
||||
(they only work if server was compiled with openssl).
|
||||
*/
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/* return values from my_aes_encrypt/my_aes_decrypt functions */
|
||||
#define MY_AES_OK 0
|
||||
#define MY_AES_BAD_DATA -100
|
||||
#define MY_AES_OPENSSL_ERROR -101
|
||||
#define MY_AES_BAD_KEYSIZE -102
|
||||
|
||||
/* The block size for all supported algorithms */
|
||||
#define MY_AES_BLOCK_SIZE 16
|
||||
|
||||
/* The max key length of all supported algorithms */
|
||||
#define MY_AES_MAX_KEY_LENGTH 32
|
||||
|
||||
#define MY_AES_CTX_SIZE 512
|
||||
|
||||
enum my_aes_mode {
|
||||
MY_AES_ECB, MY_AES_CBC
|
||||
#ifdef HAVE_EncryptAes128Ctr
|
||||
, MY_AES_CTR
|
||||
#endif
|
||||
#ifdef HAVE_EncryptAes128Gcm
|
||||
, MY_AES_GCM
|
||||
#endif
|
||||
};
|
||||
|
||||
extern struct my_crypt_service_st {
|
||||
int (*my_aes_crypt_init)(void *ctx, enum my_aes_mode mode, int flags,
|
||||
const unsigned char* key, unsigned int klen,
|
||||
const unsigned char* iv, unsigned int ivlen);
|
||||
int (*my_aes_crypt_update)(void *ctx, const unsigned char *src, unsigned int slen,
|
||||
unsigned char *dst, unsigned int *dlen);
|
||||
int (*my_aes_crypt_finish)(void *ctx, unsigned char *dst, unsigned int *dlen);
|
||||
int (*my_aes_crypt)(enum my_aes_mode mode, int flags,
|
||||
const unsigned char *src, unsigned int slen, unsigned char *dst, unsigned int *dlen,
|
||||
const unsigned char *key, unsigned int klen, const unsigned char *iv, unsigned int ivlen);
|
||||
unsigned int (*my_aes_get_size)(enum my_aes_mode mode, unsigned int source_length);
|
||||
unsigned int (*my_aes_ctx_size)(enum my_aes_mode mode);
|
||||
int (*my_random_bytes)(unsigned char* buf, int num);
|
||||
} *my_crypt_service;
|
||||
|
||||
#ifdef MYSQL_DYNAMIC_PLUGIN
|
||||
|
||||
#define my_aes_crypt_init(A,B,C,D,E,F,G) \
|
||||
my_crypt_service->my_aes_crypt_init(A,B,C,D,E,F,G)
|
||||
|
||||
#define my_aes_crypt_update(A,B,C,D,E) \
|
||||
my_crypt_service->my_aes_crypt_update(A,B,C,D,E)
|
||||
|
||||
#define my_aes_crypt_finish(A,B,C) \
|
||||
my_crypt_service->my_aes_crypt_finish(A,B,C)
|
||||
|
||||
#define my_aes_crypt(A,B,C,D,E,F,G,H,I,J) \
|
||||
my_crypt_service->my_aes_crypt(A,B,C,D,E,F,G,H,I,J)
|
||||
|
||||
#define my_aes_get_size(A,B)\
|
||||
my_crypt_service->my_aes_get_size(A,B)
|
||||
|
||||
#define my_aes_ctx_size(A)\
|
||||
my_crypt_service->my_aes_ctx_size(A)
|
||||
|
||||
#define my_random_bytes(A,B)\
|
||||
my_crypt_service->my_random_bytes(A,B)
|
||||
|
||||
#else
|
||||
|
||||
int my_aes_crypt_init(void *ctx, enum my_aes_mode mode, int flags,
|
||||
const unsigned char* key, unsigned int klen,
|
||||
const unsigned char* iv, unsigned int ivlen);
|
||||
int my_aes_crypt_update(void *ctx, const unsigned char *src, unsigned int slen,
|
||||
unsigned char *dst, unsigned int *dlen);
|
||||
int my_aes_crypt_finish(void *ctx, unsigned char *dst, unsigned int *dlen);
|
||||
int my_aes_crypt(enum my_aes_mode mode, int flags,
|
||||
const unsigned char *src, unsigned int slen, unsigned char *dst, unsigned int *dlen,
|
||||
const unsigned char *key, unsigned int klen, const unsigned char *iv, unsigned int ivlen);
|
||||
|
||||
int my_random_bytes(unsigned char* buf, int num);
|
||||
unsigned int my_aes_get_size(enum my_aes_mode mode, unsigned int source_length);
|
||||
unsigned int my_aes_ctx_size(enum my_aes_mode mode);
|
||||
#endif
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* MYSQL_SERVICE_MY_CRYPT_INCLUDED */
|
64
include/mysql/service_my_print_error.h
Normal file
64
include/mysql/service_my_print_error.h
Normal file
|
@ -0,0 +1,64 @@
|
|||
/* Copyright (c) 2016, MariaDB
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; version 2 of the License.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */
|
||||
|
||||
#ifndef MYSQL_SERVICE_MY_PRINT_ERROR_INCLUDED
|
||||
#define MYSQL_SERVICE_MY_PRINT_ERROR_INCLUDED
|
||||
|
||||
/**
|
||||
@file include/mysql/service_my_print_error.h
|
||||
|
||||
This service provides functions for plugins to report
|
||||
errors to client (without client, the errors are written to the error log).
|
||||
|
||||
*/
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#ifndef MYSQL_ABI_CHECK
|
||||
#include <stdarg.h>
|
||||
#include <stdlib.h>
|
||||
#endif
|
||||
|
||||
#define ME_ERROR_LOG 64 /* Write the message to the error log */
|
||||
#define ME_NOTE 1024 /* Not an error, just a note */
|
||||
#define ME_WARNING 2048 /* Not an error, just a warning */
|
||||
#define ME_FATAL 4096 /* Fatal statement error */
|
||||
|
||||
extern struct my_print_error_service_st {
|
||||
void (*my_error_func)(unsigned int nr, unsigned long MyFlags, ...);
|
||||
void (*my_printf_error_func)(unsigned int nr, const char *fmt, unsigned long MyFlags,...);
|
||||
void (*my_printv_error_func)(unsigned int error, const char *format, unsigned long MyFlags, va_list ap);
|
||||
} *my_print_error_service;
|
||||
|
||||
#ifdef MYSQL_DYNAMIC_PLUGIN
|
||||
|
||||
#define my_error my_print_error_service->my_error_func
|
||||
#define my_printf_error my_print_error_service->my_printf_error_func
|
||||
#define my_printv_error(A,B,C,D) my_print_error_service->my_printv_error_func(A,B,C,D)
|
||||
|
||||
#else
|
||||
|
||||
extern void my_error(unsigned int nr, unsigned long MyFlags, ...);
|
||||
extern void my_printf_error(unsigned int my_err, const char *format, unsigned long MyFlags, ...);
|
||||
extern void my_printv_error(unsigned int error, const char *format, unsigned long MyFlags,va_list ap);
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
|
@ -26,6 +26,8 @@ extern "C" {
|
|||
#include <mysql/service_kill_statement.h>
|
||||
#include <mysql/service_logger.h>
|
||||
#include <mysql/service_md5.h>
|
||||
#include <mysql/service_my_crypt.h>
|
||||
#include <mysql/service_my_print_error.h>
|
||||
#include <mysql/service_my_snprintf.h>
|
||||
#include <mysql/service_progress_report.h>
|
||||
#include <mysql/service_sha1.h>
|
||||
|
|
|
@ -27,7 +27,9 @@
|
|||
#define VERSION_encryption 0x0300
|
||||
#define VERSION_encryption_scheme 0x0100
|
||||
#define VERSION_logger 0x0100
|
||||
#define VERSION_my_crypt 0x0100
|
||||
#define VERSION_my_md5 0x0100
|
||||
#define VERSION_my_print_error 0x0100
|
||||
#define VERSION_my_sha1 0x0101
|
||||
#define VERSION_my_sha2 0x0100
|
||||
#define VERSION_my_snprintf 0x0100
|
||||
|
|
|
@ -22,7 +22,9 @@ SET(MYSQLSERVICES_SOURCES
|
|||
encryption_service.c
|
||||
kill_statement_service.c
|
||||
logger_service.c
|
||||
my_crypt_service.c
|
||||
my_md5_service.c
|
||||
my_print_error_service.c
|
||||
my_sha1_service.c
|
||||
my_sha2_service.c
|
||||
my_snprintf_service.c
|
||||
|
@ -35,7 +37,7 @@ SET(MYSQLSERVICES_SOURCES
|
|||
thd_timezone_service.c
|
||||
thd_wait_service.c
|
||||
wsrep_service.c
|
||||
)
|
||||
)
|
||||
|
||||
ADD_CONVENIENCE_LIBRARY(mysqlservices ${MYSQLSERVICES_SOURCES})
|
||||
INSTALL(TARGETS mysqlservices DESTINATION ${INSTALL_LIBDIR} COMPONENT Development)
|
||||
|
|
2
libservices/my_crypt_service.c
Normal file
2
libservices/my_crypt_service.c
Normal file
|
@ -0,0 +1,2 @@
|
|||
#include <service_versions.h>
|
||||
SERVICE_VERSION my_crypt_service= (void*)VERSION_my_crypt;
|
17
libservices/my_print_error_service.c
Normal file
17
libservices/my_print_error_service.c
Normal file
|
@ -0,0 +1,17 @@
|
|||
/* Copyright (c) 2016 MariaDB
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; version 2 of the License.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */
|
||||
|
||||
#include <service_versions.h>
|
||||
SERVICE_VERSION my_print_error_service= (void*)VERSION_my_print_error;
|
|
@ -20,3 +20,9 @@ default-character-set=latin1
|
|||
|
||||
[mysql_upgrade]
|
||||
default-character-set=latin1
|
||||
|
||||
[mysqltest]
|
||||
loose-ssl-ca=@ENV.MYSQL_TEST_DIR/std_data/cacert.pem
|
||||
loose-ssl-cert=@ENV.MYSQL_TEST_DIR/std_data/client-cert.pem
|
||||
loose-ssl-key=@ENV.MYSQL_TEST_DIR/std_data/client-key.pem
|
||||
loose-skip-ssl
|
||||
|
|
|
@ -108,6 +108,10 @@ binlog-direct-non-transactional-updates
|
|||
|
||||
default-storage-engine=myisam
|
||||
|
||||
loose-ssl-ca=@ENV.MYSQL_TEST_DIR/std_data/cacert.pem
|
||||
loose-ssl-cert=@ENV.MYSQL_TEST_DIR/std_data/server-cert.pem
|
||||
loose-ssl-key=@ENV.MYSQL_TEST_DIR/std_data/server-key.pem
|
||||
|
||||
# here, at the end of [mysqld] group mtr will automatically disable
|
||||
# all optional plugins.
|
||||
|
||||
|
|
|
@ -43,9 +43,8 @@ if ($write_to_file == 'GENERATE')
|
|||
|
||||
if (`SELECT LENGTH(@@secure_file_priv) > 0`)
|
||||
{
|
||||
--let $_wvtf_secure_file_priv= `SELECT @@secure_file_priv`
|
||||
--let $_wvtf_suffix= `SELECT UUID()`
|
||||
--let $_wvtf_tmp_file= $_wvtf_secure_file_priv/_wvtf_$_wvtf_suffix
|
||||
--let $_wvtf_tmp_file= $MYSQLTEST_VARDIR/_wvtf_$_wvtf_suffix
|
||||
|
||||
--eval SELECT '$write_var' INTO DUMPFILE '$_wvtf_tmp_file'
|
||||
--copy_file $_wvtf_tmp_file $write_to_file
|
||||
|
|
|
@ -182,55 +182,6 @@ sub fix_log_slow_queries {
|
|||
return "$dir/mysqld-slow.log";
|
||||
}
|
||||
|
||||
sub fix_std_data {
|
||||
my ($self, $config, $group_name, $group)= @_;
|
||||
my $testdir= $self->get_testdir($group);
|
||||
return "$testdir/std_data";
|
||||
}
|
||||
|
||||
sub ssl_supported {
|
||||
my ($self)= @_;
|
||||
return $self->{ARGS}->{ssl};
|
||||
}
|
||||
|
||||
sub fix_skip_ssl {
|
||||
return if !ssl_supported(@_);
|
||||
# Add skip-ssl if ssl is supported to avoid
|
||||
# that mysqltest connects with SSL by default
|
||||
return 1;
|
||||
}
|
||||
|
||||
sub fix_ssl_ca {
|
||||
return if !ssl_supported(@_);
|
||||
my $std_data= fix_std_data(@_);
|
||||
return "$std_data/cacert.pem"
|
||||
}
|
||||
|
||||
sub fix_ssl_server_cert {
|
||||
return if !ssl_supported(@_);
|
||||
my $std_data= fix_std_data(@_);
|
||||
return "$std_data/server-cert.pem"
|
||||
}
|
||||
|
||||
sub fix_ssl_client_cert {
|
||||
return if !ssl_supported(@_);
|
||||
my $std_data= fix_std_data(@_);
|
||||
return "$std_data/client-cert.pem"
|
||||
}
|
||||
|
||||
sub fix_ssl_server_key {
|
||||
return if !ssl_supported(@_);
|
||||
my $std_data= fix_std_data(@_);
|
||||
return "$std_data/server-key.pem"
|
||||
}
|
||||
|
||||
sub fix_ssl_client_key {
|
||||
return if !ssl_supported(@_);
|
||||
my $std_data= fix_std_data(@_);
|
||||
return "$std_data/client-key.pem"
|
||||
}
|
||||
|
||||
|
||||
#
|
||||
# Rules to run for each mysqld in the config
|
||||
# - will be run in order listed here
|
||||
|
@ -255,9 +206,6 @@ my @mysqld_rules=
|
|||
{ '#user' => sub { return shift->{ARGS}->{user} || ""; } },
|
||||
{ '#password' => sub { return shift->{ARGS}->{password} || ""; } },
|
||||
{ 'server-id' => \&fix_server_id, },
|
||||
{ 'ssl-ca' => \&fix_ssl_ca },
|
||||
{ 'ssl-cert' => \&fix_ssl_server_cert },
|
||||
{ 'ssl-key' => \&fix_ssl_server_key },
|
||||
{ 'bind-address' => \&fix_bind_address },
|
||||
);
|
||||
|
||||
|
@ -284,10 +232,6 @@ my @client_rules=
|
|||
#
|
||||
my @mysqltest_rules=
|
||||
(
|
||||
{ 'ssl-ca' => \&fix_ssl_ca },
|
||||
{ 'ssl-cert' => \&fix_ssl_client_cert },
|
||||
{ 'ssl-key' => \&fix_ssl_client_key },
|
||||
{ 'skip-ssl' => \&fix_skip_ssl },
|
||||
);
|
||||
|
||||
|
||||
|
|
|
@ -1,30 +1,39 @@
|
|||
#!/bin/sh -xe
|
||||
#!/bin/sh
|
||||
|
||||
set -xe
|
||||
|
||||
# simply run me from mysql-test/
|
||||
cd std_data/
|
||||
|
||||
# boilerplace for "openssl ca" and /etc/ssl/openssl.cnf
|
||||
rm -rf demoCA
|
||||
mkdir demoCA demoCA/private demoCA/newcerts
|
||||
mkdir demoCA demoCA/newcerts
|
||||
touch demoCA/index.txt
|
||||
echo 01 > demoCA/serial
|
||||
|
||||
# CA certificate, self-signed
|
||||
openssl req -x509 -newkey rsa:2048 -keyout demoCA/private/cakey.pem -out cacert.pem -days 7300 -nodes -subj '/CN=cacert/C=FI/ST=Helsinki/L=Helsinki/O=MariaDB' -text
|
||||
openssl req -x509 -newkey rsa:2048 -keyout cakey.pem -out cacert.pem -days 7300 -nodes -subj '/CN=cacert/C=FI/ST=Helsinki/L=Helsinki/O=MariaDB' -text
|
||||
|
||||
# server certificate signing request and private key. Note the very long subject (for MDEV-7859)
|
||||
openssl req -newkey rsa:1024 -keyout server-key.pem -out demoCA/server-req.pem -days 7300 -nodes -subj '/CN=localhost/C=FI/ST=state or province within country, in other certificates in this file it is the same as L/L=location, usually an address but often ambiguously used/OU=organizational unit name, a division name within an organization/O=organization name, typically a company name'
|
||||
# convert the key to yassl compatible format
|
||||
openssl rsa -in server-key.pem -out server-key.pem
|
||||
# sign the server certificate with CA certificate
|
||||
openssl ca -days 7300 -batch -cert cacert.pem -policy policy_anything -out server-cert.pem -infiles demoCA/server-req.pem
|
||||
openssl ca -keyfile cakey.pem -days 7300 -batch -cert cacert.pem -policy policy_anything -out server-cert.pem -infiles demoCA/server-req.pem
|
||||
|
||||
openssl req -newkey rsa:8192 -keyout server8k-key.pem -out demoCA/server8k-req.pem -days 7300 -nodes -subj '/CN=server8k/C=FI/ST=Helsinki/L=Helsinki/O=MariaDB'
|
||||
openssl rsa -in server8k-key.pem -out server8k-key.pem
|
||||
openssl ca -days 7300 -batch -cert cacert.pem -policy policy_anything -out server8k-cert.pem -infiles demoCA/server8k-req.pem
|
||||
openssl ca -keyfile cakey.pem -days 7300 -batch -cert cacert.pem -policy policy_anything -out server8k-cert.pem -infiles demoCA/server8k-req.pem
|
||||
|
||||
openssl req -newkey rsa:1024 -keyout client-key.pem -out demoCA/client-req.pem -days 7300 -nodes -subj '/CN=client/C=FI/ST=Helsinki/L=Helsinki/O=MariaDB'
|
||||
openssl rsa -in client-key.pem -out client-key.pem
|
||||
openssl ca -days 7300 -batch -cert cacert.pem -policy policy_anything -out client-cert.pem -infiles demoCA/client-req.pem
|
||||
openssl ca -keyfile cakey.pem -days 7300 -batch -cert cacert.pem -policy policy_anything -out client-cert.pem -infiles demoCA/client-req.pem
|
||||
|
||||
# with SubjectAltName, only for OpenSSL 1.0.2+
|
||||
cat > demoCA/sanext.conf <<EOF
|
||||
subjectAltName=DNS:localhost
|
||||
EOF
|
||||
openssl req -newkey rsa:1024 -keyout serversan-key.pem -out demoCA/serversan-req.pem -days 7300 -nodes -subj '/CN=server/C=FI/ST=Helsinki/L=Helsinki/O=MariaDB'
|
||||
openssl ca -keyfile cakey.pem -extfile demoCA/sanext.conf -days 7300 -batch -cert cacert.pem -policy policy_anything -out serversan-cert.pem -infiles demoCA/serversan-req.pem
|
||||
|
||||
rm -rf demoCA
|
||||
|
|
|
@ -184,6 +184,7 @@ my @DEFAULT_SUITES= qw(
|
|||
innodb_zip-
|
||||
json-
|
||||
maria-
|
||||
mariabackup-
|
||||
multi_source-
|
||||
optimizer_unfixed_bugs-
|
||||
parts-
|
||||
|
|
|
@ -5,7 +5,7 @@ plugin_version 1.0
|
|||
plugin_status ACTIVE
|
||||
plugin_type DAEMON
|
||||
plugin_library handlersocket.so
|
||||
plugin_library_version 1.12
|
||||
plugin_library_version 1.13
|
||||
plugin_author higuchi dot akira at dena dot jp
|
||||
plugin_description Direct access into InnoDB
|
||||
plugin_license BSD
|
||||
|
|
|
@ -1,132 +0,0 @@
|
|||
#
|
||||
# Ensure the plugin isn't loaded.
|
||||
#
|
||||
SELECT * FROM mysql.plugin WHERE dl like 'libdaemon%' ORDER BY name;
|
||||
name dl
|
||||
#
|
||||
# Enable the plugin...
|
||||
#
|
||||
#
|
||||
# Simulate loading a plugin libary with multiple entry points.
|
||||
# This will test the DISABLE to ensure all rows are removed.
|
||||
#
|
||||
INSERT INTO mysql.plugin VALUES ('wicky', 'libdaemon_example.so');
|
||||
INSERT INTO mysql.plugin VALUES ('wacky', 'libdaemon_example.so');
|
||||
INSERT INTO mysql.plugin VALUES ('wonky', 'libdaemon_example.so');
|
||||
#
|
||||
# Ensure the plugin is now loaded.
|
||||
#
|
||||
SELECT * FROM mysql.plugin WHERE dl like 'libdaemon%' ORDER BY name;
|
||||
name dl
|
||||
daemon_example libdaemon_example.so
|
||||
wacky libdaemon_example.so
|
||||
wicky libdaemon_example.so
|
||||
wonky libdaemon_example.so
|
||||
#
|
||||
# Ensure the plugin is loaded.
|
||||
#
|
||||
SELECT * FROM mysql.plugin WHERE dl like '%libdaemon%' ORDER BY name;
|
||||
name dl
|
||||
daemon_example libdaemon_example.so
|
||||
#
|
||||
# Ensure the plugin is replaced.
|
||||
#
|
||||
SELECT * FROM mysql.plugin WHERE dl like '%libdaemon%' ORDER BY name;
|
||||
name dl
|
||||
daemon_example liblibdaemon_example.so
|
||||
#
|
||||
# Disable the plugin...
|
||||
#
|
||||
#
|
||||
# Ensure the plugin isn't loaded.
|
||||
#
|
||||
SELECT * FROM mysql.plugin WHERE dl like '%libdaemon%' ORDER BY name;
|
||||
name dl
|
||||
#
|
||||
# Attempt to load non-existant plugin
|
||||
#
|
||||
ERROR: Cannot read plugin config file NOT_THERE_AT_ALL. File does not exist.
|
||||
#
|
||||
# Attempt to use non-existant plugin.ini file
|
||||
#
|
||||
ERROR: Cannot read plugin config file daemon_example. File does not exist.
|
||||
#
|
||||
# Attempt to omit the plugin
|
||||
#
|
||||
ERROR: No plugin specified.
|
||||
#
|
||||
# Attempt to omit DISABLE|ENABLE
|
||||
#
|
||||
ERROR: missing operation. Please specify either '<plugin> ENABLE' or '<plugin> DISABLE'.
|
||||
#
|
||||
# Attempt to use bad paths - datadir
|
||||
#
|
||||
ERROR: Cannot access datadir at '/data_not_there/'.
|
||||
#
|
||||
# Attempt to use bad paths - basedir
|
||||
#
|
||||
ERROR: Cannot access basedir at '/basedir_not_there/'.
|
||||
#
|
||||
# Attempt to use bad paths - plugin_dir
|
||||
#
|
||||
ERROR: Cannot read plugin config file daemon_example. File does not exist.
|
||||
#
|
||||
# Attempt to use bad paths - mysqld
|
||||
#
|
||||
ERROR: Cannot access mysqld path '/mysqld_not_there/'.
|
||||
#
|
||||
# Attempt to use bad paths - my_print_defaults
|
||||
#
|
||||
ERROR: Cannot access my-print-defaults path '/my_print_defaults_not_there/'.
|
||||
#
|
||||
# Missing library
|
||||
#
|
||||
ERROR: The plugin library is missing or in a different location.
|
||||
#
|
||||
# Bad format for config file
|
||||
#
|
||||
ERROR: Cannot read plugin config file daemon_example. Bad format in plugin configuration file.
|
||||
#
|
||||
# Missing base_dir option
|
||||
#
|
||||
ERROR: Missing --basedir option.
|
||||
#
|
||||
# Missing data_dir option
|
||||
#
|
||||
ERROR: Missing --datadir option.
|
||||
#
|
||||
# Missing plugin_dir option
|
||||
#
|
||||
ERROR: Missing --plugin_dir option.
|
||||
#
|
||||
# Show the help.
|
||||
#
|
||||
mysql_plugin Ver V.V.VV Distrib XX.XX.XX
|
||||
Copyright (c) 2011, 2015, Oracle and/or its affiliates. All rights reserved.
|
||||
|
||||
Enable or disable plugins.
|
||||
|
||||
Usage: mysql_plugin [options] <plugin> ENABLE|DISABLE
|
||||
|
||||
Options:
|
||||
-?, --help Display this help and exit.
|
||||
-b, --basedir=name The basedir for the server.
|
||||
-d, --datadir=name The datadir for the server.
|
||||
-p, --plugin-dir=name
|
||||
The plugin dir for the server.
|
||||
-i, --plugin-ini=name
|
||||
Read plugin information from configuration file specified
|
||||
instead of from <plugin-dir>/<plugin_name>.ini.
|
||||
-n, --no-defaults Do not read values from configuration file.
|
||||
-P, --print-defaults
|
||||
Show default values from configuration file.
|
||||
-m, --mysqld=name Path to mysqld executable. Example: /sbin/temp1/mysql/bin
|
||||
-f, --my-print-defaults=name
|
||||
Path to my_print_defaults executable. Example:
|
||||
/source/temp11/extra
|
||||
-v, --verbose More verbose output; you can use this multiple times to
|
||||
get even more verbose output.
|
||||
-V, --version Output version information and exit.
|
||||
|
||||
|
||||
mysql_plugin Ver V.V.VV Distrib XX.XX.XX
|
|
@ -12,7 +12,7 @@ PLUGIN_STATUS ACTIVE
|
|||
PLUGIN_TYPE STORAGE ENGINE
|
||||
PLUGIN_TYPE_VERSION #
|
||||
PLUGIN_LIBRARY ha_example.so
|
||||
PLUGIN_LIBRARY_VERSION 1.12
|
||||
PLUGIN_LIBRARY_VERSION 1.13
|
||||
PLUGIN_AUTHOR Brian Aker, MySQL AB
|
||||
PLUGIN_DESCRIPTION Example storage engine
|
||||
PLUGIN_LICENSE GPL
|
||||
|
@ -25,7 +25,7 @@ PLUGIN_STATUS ACTIVE
|
|||
PLUGIN_TYPE DAEMON
|
||||
PLUGIN_TYPE_VERSION #
|
||||
PLUGIN_LIBRARY ha_example.so
|
||||
PLUGIN_LIBRARY_VERSION 1.12
|
||||
PLUGIN_LIBRARY_VERSION 1.13
|
||||
PLUGIN_AUTHOR Sergei Golubchik
|
||||
PLUGIN_DESCRIPTION Unusable Daemon
|
||||
PLUGIN_LICENSE GPL
|
||||
|
@ -64,7 +64,7 @@ PLUGIN_STATUS DELETED
|
|||
PLUGIN_TYPE STORAGE ENGINE
|
||||
PLUGIN_TYPE_VERSION #
|
||||
PLUGIN_LIBRARY ha_example.so
|
||||
PLUGIN_LIBRARY_VERSION 1.12
|
||||
PLUGIN_LIBRARY_VERSION 1.13
|
||||
PLUGIN_AUTHOR Brian Aker, MySQL AB
|
||||
PLUGIN_DESCRIPTION Example storage engine
|
||||
PLUGIN_LICENSE GPL
|
||||
|
|
|
@ -4,10 +4,10 @@ have_ssl
|
|||
1
|
||||
SHOW STATUS LIKE 'Ssl_server_not_before';
|
||||
Variable_name Value
|
||||
Ssl_server_not_before Apr 25 14:55:05 2015 GMT
|
||||
Ssl_server_not_before Apr 25 20:52:21 2017 GMT
|
||||
SHOW STATUS LIKE 'Ssl_server_not_after';
|
||||
Variable_name Value
|
||||
Ssl_server_not_after Apr 20 14:55:05 2035 GMT
|
||||
Ssl_server_not_after Apr 20 20:52:21 2037 GMT
|
||||
drop table if exists t1,t2,t3,t4;
|
||||
CREATE TABLE t1 (
|
||||
Period smallint(4) unsigned zerofill DEFAULT '0000' NOT NULL,
|
||||
|
|
|
@ -1,78 +1,79 @@
|
|||
Certificate:
|
||||
Data:
|
||||
Version: 3 (0x2)
|
||||
Serial Number: 11580370790696127632 (0xa0b5bde0f2c08c90)
|
||||
Signature Algorithm: sha1WithRSAEncryption
|
||||
Serial Number:
|
||||
e5:b1:e3:71:e9:6f:a9:e1
|
||||
Signature Algorithm: sha256WithRSAEncryption
|
||||
Issuer: CN=cacert, C=FI, ST=Helsinki, L=Helsinki, O=MariaDB
|
||||
Validity
|
||||
Not Before: Apr 25 14:55:05 2015 GMT
|
||||
Not After : Apr 20 14:55:05 2035 GMT
|
||||
Not Before: Apr 25 20:52:21 2017 GMT
|
||||
Not After : Apr 20 20:52:21 2037 GMT
|
||||
Subject: CN=cacert, C=FI, ST=Helsinki, L=Helsinki, O=MariaDB
|
||||
Subject Public Key Info:
|
||||
Public Key Algorithm: rsaEncryption
|
||||
Public-Key: (2048 bit)
|
||||
Modulus:
|
||||
00:c0:1f:90:7c:2b:c2:ea:01:93:ce:e0:c5:72:e8:
|
||||
1c:06:bd:63:4e:b6:d2:c6:00:32:13:27:42:9e:c9:
|
||||
3c:91:33:4d:15:90:67:7d:9d:d8:be:9b:12:e2:f6:
|
||||
1b:46:81:4a:8b:10:c5:b8:14:53:ab:6a:2c:c3:7f:
|
||||
66:87:6c:0e:18:51:4e:9c:93:7a:6d:a1:d4:06:47:
|
||||
58:61:a6:04:21:2c:bd:74:7a:e4:68:45:fe:91:fe:
|
||||
fb:a6:29:47:ec:c5:c3:88:c8:c9:e7:d7:c6:1a:0d:
|
||||
b8:f5:c5:02:57:25:01:cc:d5:8c:37:46:58:c6:71:
|
||||
30:ee:63:38:99:84:5e:9e:3c:af:40:d4:f0:f2:12:
|
||||
44:6e:2f:4d:cd:f9:da:4d:0e:1f:a6:fe:35:c3:9d:
|
||||
40:08:82:5e:6f:7d:4d:09:16:7d:a1:78:d6:9f:9f:
|
||||
44:d6:b1:ad:e7:50:25:1a:f3:4e:16:92:4a:17:5e:
|
||||
0b:e1:c8:9f:62:22:c4:e2:01:96:63:ed:37:a2:e5:
|
||||
70:b9:dc:c8:8e:c4:fe:00:21:f5:b9:48:c0:43:55:
|
||||
4a:d8:0c:9d:ce:d6:60:30:bb:81:31:c8:e9:0e:aa:
|
||||
1c:18:3d:e4:10:47:42:17:c0:4d:fb:f5:d9:c2:e4:
|
||||
07:33:f7:15:94:63:6d:11:ad:4f:d4:1d:11:41:c1:
|
||||
e2:dd
|
||||
00:a0:ad:d5:b1:ec:45:6f:d6:33:fc:5a:03:29:14:
|
||||
f1:8e:78:d5:27:53:79:e0:92:7c:10:3b:79:a0:d7:
|
||||
b6:9d:a8:5c:4d:fa:68:11:b3:03:9e:ee:5e:20:79:
|
||||
23:d8:9c:49:34:9c:1d:c4:6e:53:1f:9a:92:1f:08:
|
||||
c1:15:e2:ad:cf:59:cd:1e:55:84:79:f9:09:ca:36:
|
||||
8a:50:83:c6:38:48:c6:d3:fa:f6:f2:2a:4f:bd:5d:
|
||||
60:9d:eb:21:c4:8c:f2:dd:2d:49:10:63:46:47:de:
|
||||
2d:59:a0:4a:e0:58:e6:c0:ae:d8:d4:5e:9a:f8:f5:
|
||||
68:1d:ea:80:8a:d6:01:b0:d5:5f:30:4d:88:5a:c5:
|
||||
1f:81:92:c1:40:54:c8:bb:a6:a1:43:de:81:3c:4b:
|
||||
79:95:82:bb:52:da:a3:a4:a0:69:ff:7e:00:8c:86:
|
||||
85:ec:af:03:68:a8:83:48:a0:e4:1d:31:a9:5c:47:
|
||||
99:9d:3a:3f:b5:3e:12:7c:4d:47:15:72:f1:11:5c:
|
||||
4a:ef:08:1c:7b:8f:e6:03:06:07:4f:94:21:b0:5e:
|
||||
27:fa:93:8c:b4:cc:56:34:3b:6d:c4:4a:14:57:b2:
|
||||
21:1a:3e:2f:c5:9e:47:1a:59:05:22:0e:56:b1:a7:
|
||||
e8:80:9b:82:c3:54:57:12:05:94:79:a2:03:d9:64:
|
||||
3c:63
|
||||
Exponent: 65537 (0x10001)
|
||||
X509v3 extensions:
|
||||
X509v3 Subject Key Identifier:
|
||||
C7:2C:01:95:1A:F5:3E:CD:04:A6:24:35:35:04:D9:A7:16:01:2A:79
|
||||
1C:C7:2B:AA:1B:B1:BB:2E:9A:F4:0F:B1:86:60:57:38:C2:41:05:12
|
||||
X509v3 Authority Key Identifier:
|
||||
keyid:C7:2C:01:95:1A:F5:3E:CD:04:A6:24:35:35:04:D9:A7:16:01:2A:79
|
||||
keyid:1C:C7:2B:AA:1B:B1:BB:2E:9A:F4:0F:B1:86:60:57:38:C2:41:05:12
|
||||
|
||||
X509v3 Basic Constraints:
|
||||
CA:TRUE
|
||||
Signature Algorithm: sha1WithRSAEncryption
|
||||
40:6f:6a:54:f3:29:30:48:46:bd:da:46:71:64:52:14:a7:c2:
|
||||
34:b7:5e:1e:42:3d:e7:47:92:cd:87:e7:9d:5d:1a:82:77:82:
|
||||
62:32:d4:9d:b6:44:11:dc:88:78:38:a5:d3:1f:1e:be:c2:d6:
|
||||
14:b0:58:35:cd:66:22:43:97:ba:bb:e3:44:4f:9d:75:14:9f:
|
||||
6f:37:d3:50:07:09:36:bc:58:92:e8:fe:c0:a8:ba:29:55:65:
|
||||
e2:6f:8f:ab:a5:1d:4f:56:37:de:c7:b4:39:20:4c:a8:4c:db:
|
||||
56:51:12:7e:e7:7f:83:9d:c4:c7:72:8f:6f:83:f0:af:e3:37:
|
||||
1c:40:fe:5e:38:26:2f:05:46:a7:0c:a5:81:79:d6:9c:9c:d7:
|
||||
56:eb:96:fe:c7:ae:8e:4f:5e:4a:6c:3a:fa:68:be:65:60:a2:
|
||||
d3:3f:07:76:45:b3:95:3e:11:ef:3a:0e:6f:73:47:4c:90:dd:
|
||||
0b:36:b4:22:df:62:8d:58:d2:a6:34:5b:f0:06:5d:cd:bf:52:
|
||||
fa:ee:9b:4f:e8:79:18:6e:1c:6e:5f:96:10:6d:2f:02:1b:dd:
|
||||
bf:14:c9:32:3c:83:a5:6e:56:56:78:9d:ce:84:50:a4:df:cc:
|
||||
b5:a9:b1:ec:09:07:74:02:27:7a:9d:d2:96:a9:80:95:9a:f2:
|
||||
8c:e9:ef:99
|
||||
Signature Algorithm: sha256WithRSAEncryption
|
||||
0d:4b:21:52:fa:49:34:56:14:db:83:ae:1c:3d:a7:4d:3e:ea:
|
||||
55:7e:1a:37:7a:65:89:ee:19:05:94:9d:3a:ad:59:c4:38:16:
|
||||
b2:bd:02:ee:5a:a6:7e:e2:b1:21:a3:ad:af:8c:ae:c3:30:71:
|
||||
ad:d7:d2:24:0f:c4:d9:47:80:c5:95:05:1d:7c:8a:49:0a:7d:
|
||||
8b:61:ca:b5:68:3d:3e:4e:f1:c7:45:62:c8:cc:a9:2f:f3:12:
|
||||
f1:3f:92:34:7f:07:ab:d3:ac:ab:af:2d:c9:69:63:8a:b2:e5:
|
||||
35:ea:7d:b8:17:38:72:82:5f:96:3d:dc:8d:e5:11:bb:ae:f3:
|
||||
02:2d:20:77:5c:64:59:18:a6:e7:fa:c7:89:e8:30:12:14:04:
|
||||
40:5b:e9:b1:8f:86:81:b9:0d:6c:b6:fc:98:f9:b7:52:ab:8f:
|
||||
7e:53:c8:a0:05:e4:cd:0d:6b:d2:74:9f:17:7a:a1:c3:76:5e:
|
||||
f3:29:1c:c6:be:56:ab:02:f7:5d:e1:c9:21:27:6d:66:7a:41:
|
||||
29:49:a3:f8:f5:2a:e7:03:2a:7c:52:4b:f5:46:58:45:be:a4:
|
||||
4c:a0:65:37:1d:d8:ac:f8:1f:81:ca:9c:79:f0:ff:22:8c:1d:
|
||||
ce:2b:d0:1e:ce:99:f2:db:fa:66:84:e6:86:6f:19:3b:10:f1:
|
||||
92:ac:57:b2
|
||||
-----BEGIN CERTIFICATE-----
|
||||
MIIDfzCCAmegAwIBAgIJAKC1veDywIyQMA0GCSqGSIb3DQEBBQUAMFYxDzANBgNV
|
||||
MIIDfzCCAmegAwIBAgIJAOWx43Hpb6nhMA0GCSqGSIb3DQEBCwUAMFYxDzANBgNV
|
||||
BAMMBmNhY2VydDELMAkGA1UEBhMCRkkxETAPBgNVBAgMCEhlbHNpbmtpMREwDwYD
|
||||
VQQHDAhIZWxzaW5raTEQMA4GA1UECgwHTWFyaWFEQjAeFw0xNTA0MjUxNDU1MDVa
|
||||
Fw0zNTA0MjAxNDU1MDVaMFYxDzANBgNVBAMMBmNhY2VydDELMAkGA1UEBhMCRkkx
|
||||
VQQHDAhIZWxzaW5raTEQMA4GA1UECgwHTWFyaWFEQjAeFw0xNzA0MjUyMDUyMjFa
|
||||
Fw0zNzA0MjAyMDUyMjFaMFYxDzANBgNVBAMMBmNhY2VydDELMAkGA1UEBhMCRkkx
|
||||
ETAPBgNVBAgMCEhlbHNpbmtpMREwDwYDVQQHDAhIZWxzaW5raTEQMA4GA1UECgwH
|
||||
TWFyaWFEQjCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAMAfkHwrwuoB
|
||||
k87gxXLoHAa9Y0620sYAMhMnQp7JPJEzTRWQZ32d2L6bEuL2G0aBSosQxbgUU6tq
|
||||
LMN/ZodsDhhRTpyTem2h1AZHWGGmBCEsvXR65GhF/pH++6YpR+zFw4jIyefXxhoN
|
||||
uPXFAlclAczVjDdGWMZxMO5jOJmEXp48r0DU8PISRG4vTc352k0OH6b+NcOdQAiC
|
||||
Xm99TQkWfaF41p+fRNaxredQJRrzThaSShdeC+HIn2IixOIBlmPtN6LlcLncyI7E
|
||||
/gAh9blIwENVStgMnc7WYDC7gTHI6Q6qHBg95BBHQhfATfv12cLkBzP3FZRjbRGt
|
||||
T9QdEUHB4t0CAwEAAaNQME4wHQYDVR0OBBYEFMcsAZUa9T7NBKYkNTUE2acWASp5
|
||||
MB8GA1UdIwQYMBaAFMcsAZUa9T7NBKYkNTUE2acWASp5MAwGA1UdEwQFMAMBAf8w
|
||||
DQYJKoZIhvcNAQEFBQADggEBAEBvalTzKTBIRr3aRnFkUhSnwjS3Xh5CPedHks2H
|
||||
551dGoJ3gmIy1J22RBHciHg4pdMfHr7C1hSwWDXNZiJDl7q740RPnXUUn28301AH
|
||||
CTa8WJLo/sCouilVZeJvj6ulHU9WN97HtDkgTKhM21ZREn7nf4OdxMdyj2+D8K/j
|
||||
NxxA/l44Ji8FRqcMpYF51pyc11brlv7Hro5PXkpsOvpovmVgotM/B3ZFs5U+Ee86
|
||||
Dm9zR0yQ3Qs2tCLfYo1Y0qY0W/AGXc2/Uvrum0/oeRhuHG5flhBtLwIb3b8UyTI8
|
||||
g6VuVlZ4nc6EUKTfzLWpsewJB3QCJ3qd0papgJWa8ozp75k=
|
||||
TWFyaWFEQjCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAKCt1bHsRW/W
|
||||
M/xaAykU8Y541SdTeeCSfBA7eaDXtp2oXE36aBGzA57uXiB5I9icSTScHcRuUx+a
|
||||
kh8IwRXirc9ZzR5VhHn5Cco2ilCDxjhIxtP69vIqT71dYJ3rIcSM8t0tSRBjRkfe
|
||||
LVmgSuBY5sCu2NRemvj1aB3qgIrWAbDVXzBNiFrFH4GSwUBUyLumoUPegTxLeZWC
|
||||
u1Lao6Sgaf9+AIyGheyvA2iog0ig5B0xqVxHmZ06P7U+EnxNRxVy8RFcSu8IHHuP
|
||||
5gMGB0+UIbBeJ/qTjLTMVjQ7bcRKFFeyIRo+L8WeRxpZBSIOVrGn6ICbgsNUVxIF
|
||||
lHmiA9lkPGMCAwEAAaNQME4wHQYDVR0OBBYEFBzHK6obsbsumvQPsYZgVzjCQQUS
|
||||
MB8GA1UdIwQYMBaAFBzHK6obsbsumvQPsYZgVzjCQQUSMAwGA1UdEwQFMAMBAf8w
|
||||
DQYJKoZIhvcNAQELBQADggEBAA1LIVL6STRWFNuDrhw9p00+6lV+Gjd6ZYnuGQWU
|
||||
nTqtWcQ4FrK9Au5apn7isSGjra+MrsMwca3X0iQPxNlHgMWVBR18ikkKfYthyrVo
|
||||
PT5O8cdFYsjMqS/zEvE/kjR/B6vTrKuvLclpY4qy5TXqfbgXOHKCX5Y93I3lEbuu
|
||||
8wItIHdcZFkYpuf6x4noMBIUBEBb6bGPhoG5DWy2/Jj5t1Krj35TyKAF5M0Na9J0
|
||||
nxd6ocN2XvMpHMa+VqsC913hySEnbWZ6QSlJo/j1KucDKnxSS/VGWEW+pEygZTcd
|
||||
2Kz4H4HKnHnw/yKMHc4r0B7OmfLb+maE5oZvGTsQ8ZKsV7I=
|
||||
-----END CERTIFICATE-----
|
||||
|
|
28
mysql-test/std_data/cakey.pem
Normal file
28
mysql-test/std_data/cakey.pem
Normal file
|
@ -0,0 +1,28 @@
|
|||
-----BEGIN PRIVATE KEY-----
|
||||
MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQCgrdWx7EVv1jP8
|
||||
WgMpFPGOeNUnU3ngknwQO3mg17adqFxN+mgRswOe7l4geSPYnEk0nB3EblMfmpIf
|
||||
CMEV4q3PWc0eVYR5+QnKNopQg8Y4SMbT+vbyKk+9XWCd6yHEjPLdLUkQY0ZH3i1Z
|
||||
oErgWObArtjUXpr49Wgd6oCK1gGw1V8wTYhaxR+BksFAVMi7pqFD3oE8S3mVgrtS
|
||||
2qOkoGn/fgCMhoXsrwNoqINIoOQdMalcR5mdOj+1PhJ8TUcVcvERXErvCBx7j+YD
|
||||
BgdPlCGwXif6k4y0zFY0O23EShRXsiEaPi/FnkcaWQUiDlaxp+iAm4LDVFcSBZR5
|
||||
ogPZZDxjAgMBAAECggEAWmy6AGFpSmEP7IpzkOEaeAWEX5dY1YtaioAOGPiM6vje
|
||||
yXuMqblG5mBbVIcYJ0T85cCd9/fmi7ifVxvEHh7tle2Bw/p4jXQbkFNVT655FR/P
|
||||
1Wg9JVeufHFaeETlQgnYe6SKo9BaswNUHkZZHRyq7/D2Ub3UFRt2tq9MG9YIKY1m
|
||||
rP9s7E+EDuH9UhYmaWdQfNm8muIXWK8WjicI5+PX0CQ1NtUy6vS7qBzcBzvT0chC
|
||||
Jtja29S6Nvg12A96nHsRmQyUaQjRlqosSwiagpc5mZmNeCEUoY+3deIdYIUMSQnf
|
||||
judZOKVPq0GOW5Y1U068LGODWaifPkinGBj+04VH0QKBgQDOp/jVCOUdEeqFJ/8m
|
||||
wEsfsRIrXvtGJHgbDXcVJ69FwlX+yaKGEuC+4f21uyxPn6GoFw+NKAyTmGKH7VAX
|
||||
OFQLrMQ/DMlNbZrCAAFcXMqrnLaVwqMeIIoVNfKAa8u15K40qc+B0it61Nlay5wq
|
||||
wvXoSZrdqXSgsI29pav20+8pTQKBgQDHC3l1+gMZ1rCar+5KdVBN1Wq4Xh7cwZw6
|
||||
FxEvyrDCJePEU2L7FpH1pFuB4WpXdBu3CPo70ZgwfqBXn4qLOOI3gTtDHActyiUm
|
||||
+WRG62O+5Ye7aLB4xy0MfnKNA2g/yHj1ozwM8kA5JRptAzDnzWfVE0k47/pVAVzt
|
||||
E2bZuSykbwKBgQCL6SkMgjMr1T9j20phn/q8gBN/DZUtTe+K0Tj4N5/wqLuz/its
|
||||
fkdutG4ipZBAcCDwPnym4qBxJNBAmqiIr/gm11ceILgBFd2azoodUC1etoDfL6Fj
|
||||
+j/CUH3X+CM5CJPwz67Pg80wIf7t+7/FK611ELAqtllhmWa9KPcd6yqWWQKBgHh5
|
||||
Xnvk5kmWY3BNOgrBNOjXWu/asA1n9lpGqfVmVlQ8wL6MxiU5xQCMCYL0X/ws37WK
|
||||
boMUWmxHyF8gxqd7t5hm1OrKpSG274PGgUZXpRjfLqdlNyLzUzXztvvY6xloCqaK
|
||||
tYcUfYDZD0SaINi8v7L9KF2ZCsi2uXsZOjBf30BrAoGAXPPotkw/CkcPQBS13cha
|
||||
ZWeeH5NDKBADWXfLfcRUs108c9xw4BYr5yGilSPscN2ZP0/iWONKp/c6/STS54t5
|
||||
lkOKKUbkAFbQu8UKa1J7zrnHZv+Mr4I/iBBy6VkN8Spp2vBI3Ng6jhPIJg3Gum9p
|
||||
943wWtAnIhe/UqCRT3a/GZg=
|
||||
-----END PRIVATE KEY-----
|
|
@ -2,25 +2,25 @@ Certificate:
|
|||
Data:
|
||||
Version: 3 (0x2)
|
||||
Serial Number: 3 (0x3)
|
||||
Signature Algorithm: sha1WithRSAEncryption
|
||||
Signature Algorithm: sha256WithRSAEncryption
|
||||
Issuer: CN=cacert, C=FI, ST=Helsinki, L=Helsinki, O=MariaDB
|
||||
Validity
|
||||
Not Before: Apr 25 14:55:16 2015 GMT
|
||||
Not After : Apr 20 14:55:16 2035 GMT
|
||||
Not Before: Apr 25 20:52:33 2017 GMT
|
||||
Not After : Apr 20 20:52:33 2037 GMT
|
||||
Subject: C=FI, ST=Helsinki, L=Helsinki, O=MariaDB, CN=client
|
||||
Subject Public Key Info:
|
||||
Public Key Algorithm: rsaEncryption
|
||||
Public-Key: (1024 bit)
|
||||
Modulus:
|
||||
00:ce:a0:3d:3c:a4:bb:4f:a1:4f:91:0d:05:ac:5b:
|
||||
8a:15:7f:d7:aa:0c:a3:a7:9f:b2:c7:26:9d:65:28:
|
||||
b1:84:d3:a0:ef:9e:b1:45:0f:33:df:98:6e:71:ff:
|
||||
2b:66:9c:9c:c1:25:13:27:42:b6:20:46:e7:e7:47:
|
||||
a1:88:47:c2:9e:e2:45:25:99:9f:f9:28:1a:9a:13:
|
||||
67:5d:3e:b3:b8:fe:40:25:ac:26:49:46:2c:03:43:
|
||||
83:67:d8:0f:41:ae:2e:f4:d8:71:60:3c:8e:e7:91:
|
||||
d0:bb:2c:ca:12:da:71:1a:7b:e3:fa:8c:8f:c3:bb:
|
||||
62:55:89:b3:bf:85:45:01:61
|
||||
00:a1:10:ea:cc:8e:2c:73:6b:33:1a:5e:26:19:b6:
|
||||
4b:4c:bc:04:b8:c2:e2:33:eb:67:a2:7a:27:af:3f:
|
||||
f7:ef:49:5f:c1:d2:b9:d9:71:fe:17:a0:93:da:dc:
|
||||
f1:47:de:fa:1f:c3:c1:d1:a5:2a:06:cb:b3:e8:9a:
|
||||
c1:bd:78:77:68:45:c1:55:cd:b1:c1:d3:df:8c:12:
|
||||
4f:c2:3a:0d:b7:58:dc:ca:13:08:b9:fb:12:24:90:
|
||||
aa:b7:4e:04:eb:43:0d:45:be:1c:17:d6:a8:b1:af:
|
||||
10:3c:39:d6:08:45:ed:a9:7e:3a:69:ae:70:22:86:
|
||||
7e:71:1f:f1:0e:d0:0d:32:c3
|
||||
Exponent: 65537 (0x10001)
|
||||
X509v3 extensions:
|
||||
X509v3 Basic Constraints:
|
||||
|
@ -28,42 +28,42 @@ Certificate:
|
|||
Netscape Comment:
|
||||
OpenSSL Generated Certificate
|
||||
X509v3 Subject Key Identifier:
|
||||
5A:73:74:8E:14:29:C3:FB:B4:19:0F:97:8F:AA:6F:E1:E1:A8:F7:5B
|
||||
0C:20:76:A1:80:9C:2F:30:3D:F7:AB:8D:31:19:AD:E2:F7:E2:8D:12
|
||||
X509v3 Authority Key Identifier:
|
||||
keyid:C7:2C:01:95:1A:F5:3E:CD:04:A6:24:35:35:04:D9:A7:16:01:2A:79
|
||||
keyid:1C:C7:2B:AA:1B:B1:BB:2E:9A:F4:0F:B1:86:60:57:38:C2:41:05:12
|
||||
|
||||
Signature Algorithm: sha1WithRSAEncryption
|
||||
32:42:4b:36:44:a5:6c:fb:70:d8:08:2b:cb:16:34:15:db:39:
|
||||
60:7b:7e:b4:4a:bc:fb:e5:16:04:97:0d:eb:f5:68:95:da:2f:
|
||||
23:57:4c:c9:29:2b:d1:1b:1b:9f:bd:f4:79:75:df:62:7f:63:
|
||||
b4:84:7a:95:5c:c4:ee:f3:77:16:e4:0b:8a:5e:c9:64:bd:7c:
|
||||
04:50:ac:ff:9a:41:6b:b1:6a:9f:cd:45:10:72:83:10:8a:26:
|
||||
1d:7f:6c:84:34:5a:41:79:72:91:ee:87:5d:1d:3a:55:ff:91:
|
||||
7e:52:85:ff:42:41:eb:76:56:23:e5:bc:bc:79:b1:aa:4e:4c:
|
||||
bf:7b:df:63:8b:1a:3c:4b:01:72:89:35:bb:0d:92:97:16:6e:
|
||||
ae:50:cb:89:ee:c6:7a:d0:d3:32:22:0f:19:33:1e:ee:ff:41:
|
||||
a5:a1:25:c5:4c:ce:8f:98:4c:b5:2c:1f:ec:cc:f1:21:e2:3a:
|
||||
ff:7d:6a:87:fe:89:fd:2c:20:3e:fb:9b:b8:c0:f9:09:99:ce:
|
||||
45:63:82:09:1c:bb:79:d8:a8:40:21:46:c7:ae:3e:dd:89:9d:
|
||||
56:46:4a:f4:ed:7d:5b:a6:1e:a6:1b:26:f9:ec:26:b4:51:3a:
|
||||
87:b6:50:13:84:33:22:1a:8a:20:c5:44:64:b8:bb:de:32:ec:
|
||||
6b:58:db:17
|
||||
Signature Algorithm: sha256WithRSAEncryption
|
||||
39:c0:90:13:19:85:47:9d:c6:ab:8c:c6:c9:0f:33:11:19:f7:
|
||||
01:2c:1b:08:f6:81:98:11:ab:48:05:d9:b2:29:56:32:9c:ba:
|
||||
e5:40:df:85:5e:6d:fd:6e:36:9a:14:eb:90:50:57:de:2f:ed:
|
||||
2d:89:a6:8a:40:1c:41:84:9b:da:e1:6d:e6:7c:46:b2:e0:90:
|
||||
93:02:1c:52:2e:af:b4:d4:a1:d8:9d:19:cf:0a:67:bf:c3:3e:
|
||||
2e:02:f4:3e:bc:2e:59:57:30:85:8a:32:ab:22:88:72:37:6e:
|
||||
ee:ed:f8:53:72:c9:28:87:50:47:81:1b:80:4c:f8:80:ce:2f:
|
||||
47:ca:78:ce:38:51:70:ec:df:ee:fc:ea:5a:40:1e:4d:1c:fd:
|
||||
4e:f6:74:d0:22:a4:7e:57:df:16:1a:a0:8d:be:fe:ee:f2:07:
|
||||
2e:39:a1:97:40:19:f9:3b:b8:e7:c4:98:6e:1d:1a:27:d3:19:
|
||||
4c:5c:c9:c3:31:98:c1:3c:27:0e:6a:de:cf:88:72:cf:e4:65:
|
||||
c9:0d:33:32:f1:ea:f7:dd:5b:9d:42:6d:ee:c7:a8:b7:85:d2:
|
||||
41:e0:84:38:ce:86:81:ba:6e:7d:d5:ad:7a:00:58:d7:c5:83:
|
||||
9e:5c:1d:38:32:72:49:f5:42:4b:e7:c6:5c:12:6d:e1:5d:51:
|
||||
2c:f5:52:f0
|
||||
-----BEGIN CERTIFICATE-----
|
||||
MIIDHjCCAgagAwIBAgIBAzANBgkqhkiG9w0BAQUFADBWMQ8wDQYDVQQDDAZjYWNl
|
||||
MIIDHjCCAgagAwIBAgIBAzANBgkqhkiG9w0BAQsFADBWMQ8wDQYDVQQDDAZjYWNl
|
||||
cnQxCzAJBgNVBAYTAkZJMREwDwYDVQQIDAhIZWxzaW5raTERMA8GA1UEBwwISGVs
|
||||
c2lua2kxEDAOBgNVBAoMB01hcmlhREIwHhcNMTUwNDI1MTQ1NTE2WhcNMzUwNDIw
|
||||
MTQ1NTE2WjBWMQswCQYDVQQGEwJGSTERMA8GA1UECAwISGVsc2lua2kxETAPBgNV
|
||||
c2lua2kxEDAOBgNVBAoMB01hcmlhREIwHhcNMTcwNDI1MjA1MjMzWhcNMzcwNDIw
|
||||
MjA1MjMzWjBWMQswCQYDVQQGEwJGSTERMA8GA1UECAwISGVsc2lua2kxETAPBgNV
|
||||
BAcMCEhlbHNpbmtpMRAwDgYDVQQKDAdNYXJpYURCMQ8wDQYDVQQDDAZjbGllbnQw
|
||||
gZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJAoGBAM6gPTyku0+hT5ENBaxbihV/16oM
|
||||
o6efsscmnWUosYTToO+esUUPM9+YbnH/K2acnMElEydCtiBG5+dHoYhHwp7iRSWZ
|
||||
n/koGpoTZ10+s7j+QCWsJklGLANDg2fYD0GuLvTYcWA8jueR0LssyhLacRp74/qM
|
||||
j8O7YlWJs7+FRQFhAgMBAAGjezB5MAkGA1UdEwQCMAAwLAYJYIZIAYb4QgENBB8W
|
||||
HU9wZW5TU0wgR2VuZXJhdGVkIENlcnRpZmljYXRlMB0GA1UdDgQWBBRac3SOFCnD
|
||||
+7QZD5ePqm/h4aj3WzAfBgNVHSMEGDAWgBTHLAGVGvU+zQSmJDU1BNmnFgEqeTAN
|
||||
BgkqhkiG9w0BAQUFAAOCAQEAMkJLNkSlbPtw2AgryxY0Fds5YHt+tEq8++UWBJcN
|
||||
6/VoldovI1dMySkr0Rsbn730eXXfYn9jtIR6lVzE7vN3FuQLil7JZL18BFCs/5pB
|
||||
a7Fqn81FEHKDEIomHX9shDRaQXlyke6HXR06Vf+RflKF/0JB63ZWI+W8vHmxqk5M
|
||||
v3vfY4saPEsBcok1uw2SlxZurlDLie7GetDTMiIPGTMe7v9BpaElxUzOj5hMtSwf
|
||||
7MzxIeI6/31qh/6J/SwgPvubuMD5CZnORWOCCRy7edioQCFGx64+3YmdVkZK9O19
|
||||
W6Yephsm+ewmtFE6h7ZQE4QzIhqKIMVEZLi73jLsa1jbFw==
|
||||
gZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJAoGBAKEQ6syOLHNrMxpeJhm2S0y8BLjC
|
||||
4jPrZ6J6J68/9+9JX8HSudlx/hegk9rc8Ufe+h/DwdGlKgbLs+iawb14d2hFwVXN
|
||||
scHT34wST8I6DbdY3MoTCLn7EiSQqrdOBOtDDUW+HBfWqLGvEDw51ghF7al+Ommu
|
||||
cCKGfnEf8Q7QDTLDAgMBAAGjezB5MAkGA1UdEwQCMAAwLAYJYIZIAYb4QgENBB8W
|
||||
HU9wZW5TU0wgR2VuZXJhdGVkIENlcnRpZmljYXRlMB0GA1UdDgQWBBQMIHahgJwv
|
||||
MD33q40xGa3i9+KNEjAfBgNVHSMEGDAWgBQcxyuqG7G7Lpr0D7GGYFc4wkEFEjAN
|
||||
BgkqhkiG9w0BAQsFAAOCAQEAOcCQExmFR53Gq4zGyQ8zERn3ASwbCPaBmBGrSAXZ
|
||||
silWMpy65UDfhV5t/W42mhTrkFBX3i/tLYmmikAcQYSb2uFt5nxGsuCQkwIcUi6v
|
||||
tNSh2J0Zzwpnv8M+LgL0PrwuWVcwhYoyqyKIcjdu7u34U3LJKIdQR4EbgEz4gM4v
|
||||
R8p4zjhRcOzf7vzqWkAeTRz9TvZ00CKkflffFhqgjb7+7vIHLjmhl0AZ+Tu458SY
|
||||
bh0aJ9MZTFzJwzGYwTwnDmrez4hyz+RlyQ0zMvHq991bnUJt7seot4XSQeCEOM6G
|
||||
gbpufdWtegBY18WDnlwdODJySfVCS+fGXBJt4V1RLPVS8A==
|
||||
-----END CERTIFICATE-----
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Reference in a new issue