From 05326563ee0703939311137fed8206b055402f5e Mon Sep 17 00:00:00 2001 From: MassimilianoPinto Date: Wed, 26 Aug 2015 10:51:35 +0200 Subject: [PATCH] Added MaxScale binlog check utility Added MaxScale binlog check utility --- server/modules/routing/binlog/CMakeLists.txt | 10 + .../modules/routing/binlog/maxbinlogcheck.c | 228 ++++++++++++++++++ 2 files changed, 238 insertions(+) create mode 100644 server/modules/routing/binlog/maxbinlogcheck.c diff --git a/server/modules/routing/binlog/CMakeLists.txt b/server/modules/routing/binlog/CMakeLists.txt index 9a0c245de..4510bbd50 100644 --- a/server/modules/routing/binlog/CMakeLists.txt +++ b/server/modules/routing/binlog/CMakeLists.txt @@ -2,3 +2,13 @@ add_library(binlogrouter SHARED blr.c blr_master.c blr_cache.c blr_slave.c blr_f set_target_properties(binlogrouter PROPERTIES INSTALL_RPATH ${CMAKE_INSTALL_RPATH}:${MAXSCALE_LIBDIR}) target_link_libraries(binlogrouter ssl pthread log_manager) install(TARGETS binlogrouter DESTINATION ${MAXSCALE_LIBDIR}) + +add_executable(maxbinlogcheck maxbinlogcheck.c blr_file.c blr_cache.c blr_master.c blr_slave.c blr.c ${CMAKE_SOURCE_DIR}/server/core/service.c ${CMAKE_SOURCE_DIR}/server/core/spinlock.c ${CMAKE_SOURCE_DIR}/server/core/buffer.c ${CMAKE_SOURCE_DIR}/server/core/atomic.c ${CMAKE_SOURCE_DIR}/server/core/hint.c ${CMAKE_SOURCE_DIR}/server/core/gwdirs.c ${CMAKE_SOURCE_DIR}/server/core/server.c ${CMAKE_SOURCE_DIR}/server/core/dcb.c ${CMAKE_SOURCE_DIR}/server/core/users.c ${CMAKE_SOURCE_DIR}/server/core/dbusers.c ${CMAKE_SOURCE_DIR}/server/core/utils.c ${CMAKE_SOURCE_DIR}/server/core/hashtable.c ${CMAKE_SOURCE_DIR}/server/core/poll.c ${CMAKE_SOURCE_DIR}/server/core/gwbitmask.c ${CMAKE_SOURCE_DIR}/server/core/config.c ${CMAKE_SOURCE_DIR}/server/core/session.c ${CMAKE_SOURCE_DIR}/server/core/housekeeper.c ${CMAKE_SOURCE_DIR}/server/core/filter.c ${CMAKE_SOURCE_DIR}/server/core/resultset.c ${CMAKE_SOURCE_DIR}/server/core/load_utils.c ${CMAKE_SOURCE_DIR}/server/core/monitor.c ${CMAKE_SOURCE_DIR}/server/core/gw_utils.c ${CMAKE_SOURCE_DIR}/server/core/thread.c ${CMAKE_SOURCE_DIR}/server/core/secrets.c) + +target_link_libraries(maxbinlogcheck utils ssl pthread log_manager ${PCRE_LINK_FLAGS} aio rt crypt dl crypto inih z m stdc++ ${EMBEDDED_LIB} ${CURL_LIBRARIES}) + +install(TARGETS maxbinlogcheck DESTINATION bin) + +if(BUILD_TESTS) + add_subdirectory(test) +endif() diff --git a/server/modules/routing/binlog/maxbinlogcheck.c b/server/modules/routing/binlog/maxbinlogcheck.c new file mode 100644 index 000000000..4ddf6dac6 --- /dev/null +++ b/server/modules/routing/binlog/maxbinlogcheck.c @@ -0,0 +1,228 @@ +/* + * GNU General Public License as published by the Free Software Foundation, + * version 2. + * + * 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. + * + * Copyright MariaDB Corporation Ab 2015 + */ + +/** + * @file maxbinlogcheck.c - The MaxScale binlog check utility + * + * This utility checks a MySQL 5.6 and MariaDB 10.0.X binlog file and reports + * any found error or an incomplete transaction. + * It suggests the pos the file should be trucatetd at. + * + * @verbatim + * Revision History + * + * Date Who Description + * 24/07/2015 Massimiliano Pinto Initial implementation + * + * @endverbatim + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include +#include +#include +#include + +#include +#include + +extern int lm_enabled_logfiles_bitmask; +extern size_t log_ses_count[]; +extern __thread log_info_t tls_log_info; +extern int blr_read_events_all_events(ROUTER_INSTANCE *router, int fix, int debug); +extern uint32_t extract_field(uint8_t *src, int bits); +static void printVersion(const char *progname); +static void printUsage(const char *progname); + +static struct option long_options[] = { + {"debug", no_argument, 0, 'd'}, + {"verbose", no_argument, 0, 'v'}, + {"version", no_argument, 0, 'V'}, + {"fix", no_argument, 0, 'f'}, + {"help", no_argument, 0, '?'}, + {0, 0, 0, 0} +}; + +int main(int argc, char **argv) { + char** arg_vector; + int arg_count = 4; + ROUTER_INSTANCE *inst; + int fd; + int ret; + char *ptr; + char path[4097] = ""; + unsigned long filelen = 0; + struct stat statb; + char c; + int option_index = 0; + int num_args = 0; + int debug_out = 0; + int verbose_out = 0; + int fix_file = 0; + + while ((c = getopt_long(argc, argv, "dvVf?", long_options, &option_index)) >= 0) + { + switch (c) { + case 'd': + debug_out = 1; + break; + case 'v': + verbose_out = 1; + break; + case 'V': + printVersion(*argv); + exit(EXIT_SUCCESS); + break; + case 'f': + fix_file = 1; + break; + case '?': + printUsage(*argv); + exit(optopt ? EXIT_FAILURE : EXIT_SUCCESS); + } + } + + num_args = optind; + + arg_vector = malloc(sizeof(char*)*(arg_count + 1)); + + if(arg_vector == NULL) + { + fprintf(stderr,"Error: Memory allocation failed for log manager arg_vector.\n"); + return 1; + } + + arg_vector[0] = "logmanager"; + arg_vector[1] = "-j"; + arg_vector[2] = "/tmp/maxbinlogcheck"; + arg_vector[3] = "-o"; + arg_vector[4] = NULL; + skygw_logmanager_init(arg_count,arg_vector); + free(arg_vector); + + if (!debug_out) + skygw_log_disable(LOGFILE_DEBUG); + + if ((inst = calloc(1, sizeof(ROUTER_INSTANCE))) == NULL) { + LOGIF(LE, (skygw_log_write_flush(LOGFILE_ERROR, + "Error: Memory allocation failed for ROUTER_INSTANCE"))); + + skygw_log_sync_all(); + skygw_logmanager_done(); + + return 1; + } + + if (argv[num_args] == NULL) { + printf("ERROR: No binlog file was specified\n"); + exit(EXIT_FAILURE); + } + + strncpy(path, argv[num_args], 4096); + + if ((fd = open(path, O_RDONLY, 0666)) == -1) + { + LOGIF(LE, (skygw_log_write(LOGFILE_ERROR, + "Failed to open binlog file %s: %s", + path, strerror(errno)))); + + skygw_log_sync_all(); + skygw_logmanager_done(); + + free(inst); + + return 1; + } + + inst->binlog_fd = fd; + + ptr = strrchr(path, '/'); + if (ptr) + strncpy(inst->binlog_name, ptr+1, 16); + + LOGIF(LM, (skygw_log_write_flush(LOGFILE_MESSAGE, + "maxbinlogcheck v1.0"))); + + if (fstat(inst->binlog_fd, &statb) == 0) + filelen = statb.st_size; + + LOGIF(LM, (skygw_log_write_flush(LOGFILE_MESSAGE, + "Checking %s (%s), size %lu", path, inst->binlog_name, filelen))); + + /* read binary log */ + ret = blr_read_events_all_events(inst, fix_file, debug_out); + + close(inst->binlog_fd); + + skygw_log_sync_all(); + + LOGIF(LM, (skygw_log_write_flush(LOGFILE_MESSAGE, + "Check retcode: %i, Binlog Pos = %llu", ret, inst->binlog_position))); + + skygw_log_sync_all(); + skygw_logmanager_done(); + + free(inst); + + return 0; +} + +/** + * Print version information + */ +static void +printVersion(const char *progname) +{ + printf("%s Version %s\n", progname, MAXSCALE_VERSION); +} + +/** + * Display the --help text. + */ +static void +printUsage(const char *progname) +{ + printVersion(progname); + + printf("The MaxScale binlog check utility.\n\n"); + printf("Usage: %s [-f] [-d] [-v] []\n\n", progname); + printf(" -f|--fix Fix binlog file, require write permissions (truncate)\n"); + printf(" -d|--debug Print debug messages\n"); + printf(" -v|--verbose Verbose output\n"); + printf(" -V|--version print version information and exit\n"); + printf(" -?|--help Print this help text\n"); +} + +