diff --git a/CMakeLists.txt b/CMakeLists.txt index ab5509402..0c133c311 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -98,7 +98,7 @@ message(STATUS "Installing MaxScale to: ${CMAKE_INSTALL_PREFIX}/") install(FILES server/MaxScale_template.cnf DESTINATION etc) install(FILES ${ERRMSG} DESTINATION mysql) install(FILES ${DOCS} DESTINATION Documentation) - +install(DIRECTORY DESTINATION log) # See if we are on a RPM-capable or DEB-capable system find_program(RPMBUILD rpmbuild) find_program(DEBBUILD dpkg-buildpackage) @@ -136,10 +136,16 @@ set(CPACK_RPM_USER_FILELIST "%ignore /etc/init.d") set(CPACK_RPM_USER_FILELIST "%ignore /etc/ld.so.conf.d") set(CPACK_RPM_USER_FILELIST "%ignore /etc") include(CPack) +add_custom_target(buildtests + COMMAND ${CMAKE_COMMAND} -DDEPS_OK=Y -DBUILD_TESTS=Y -DBUILD_TYPE=Debug -DINSTALL_DIR=${CMAKE_BINARY_DIR} -DINSTALL_SYSTEM_FILES=N ${CMAKE_SOURCE_DIR} + COMMAND make + COMMENT "Building test suite..." VERBATIM +) add_custom_target(testall COMMAND ${CMAKE_COMMAND} -DDEPS_OK=Y -DBUILD_TESTS=Y -DBUILD_TYPE=Debug -DINSTALL_DIR=${CMAKE_BINARY_DIR} -DINSTALL_SYSTEM_FILES=N ${CMAKE_SOURCE_DIR} COMMAND make install + COMMAND cp -vn ${CMAKE_SOURCE_DIR}/server/test/MaxScale_test.cnf ${CMAKE_BINARY_DIR}/etc/MaxScale.cnf COMMAND /bin/sh -c "${CMAKE_BINARY_DIR}/bin/maxscale -c ${CMAKE_BINARY_DIR} &>/dev/null" COMMAND /bin/sh -c "make test || echo \"Test results written to: ${CMAKE_BINARY_DIR}/Testing/Temporary/\"" COMMAND killall maxscale - COMMENT "Running full test suite" VERBATIM) \ No newline at end of file + COMMENT "Running full test suite..." VERBATIM) \ No newline at end of file diff --git a/README b/README index a939021d0..920c24994 100644 --- a/README +++ b/README @@ -29,7 +29,7 @@ issues and communicate with the MaxScale community. or use the [forum](http://groups.google.com/forum/#!forum/maxscale) interface Bugs can be reported in the MariaDB Corporation bugs database - [bug.skysql.com](http://bugs.skysql.com) + [bug.mariadb.com](http://bugs.mariadb.com) \section Building Building MaxScale diff --git a/VERSION b/VERSION index 1f6191473..ed69ddf2c 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -1.0.1-beta +1.0.2-beta diff --git a/client/test/maxadmin_test.sh b/client/test/maxadmin_test.sh index b04312da4..5540fc380 100644 --- a/client/test/maxadmin_test.sh +++ b/client/test/maxadmin_test.sh @@ -19,58 +19,58 @@ else fi maxadmin --password=skysql help >& /dev/null if [ $? -eq "1" ]; then - echo "Auth test (long option): Failed" + echo "Auth test (long option): Failed" failure=`expr $failure + 1` else passed=`expr $passed + 1` - echo "Auth test (long option): Passed" + echo "Auth test (long option): Passed" fi maxadmin -pskysql enable log debug >& /dev/null if [ $? -eq "1" ]; then - echo "Enable debug log: Failed" + echo "Enable debug log: Failed" failure=`expr $failure + 1` else passed=`expr $passed + 1` - echo "Enable debug log: Passed" + echo "Enable debug log: Passed" fi maxadmin -pskysql enable log trace >& /dev/null if [ $? -eq "1" ]; then - echo "Enable trace log: Failed" + echo "Enable trace log: Failed" failure=`expr $failure + 1` else passed=`expr $passed + 1` - echo "Enable trace log: Passed" + echo "Enable trace log: Passed" fi maxadmin -pskysql disable log debug >& /dev/null if [ $? -eq "1" ]; then - echo "Disable debug log: Failed" + echo "Disable debug log: Failed" failure=`expr $failure + 1` else passed=`expr $passed + 1` - echo "Disable debug log: Passed" + echo "Disable debug log: Passed" fi maxadmin -pskysql disable log trace >& /dev/null if [ $? -eq "1" ]; then - echo "Disable trace log: Failed" + echo "Disable trace log: Failed" failure=`expr $failure + 1` else passed=`expr $passed + 1` - echo "Disable trace log: Passed" + echo "Disable trace log: Passed" fi for cmd in clients dcbs filters listeners modules monitors services servers sessions threads do maxadmin -pskysql list $cmd | grep -s '-' >& /dev/null if [ $? -eq "1" ]; then - echo "list command ($cmd): Failed" + echo "list command ($cmd): Failed" failure=`expr $failure + 1` else passed=`expr $passed + 1` - echo "list command ($cmd): Passed" + echo "list command ($cmd): Passed" fi done @@ -206,5 +206,110 @@ do fi done +maxadmin -pskysql list services | \ + awk -F\| '{ if (NF > 1) { sub(/ +$/, "", $1); printf("show service \"%s\"\n", $1); } }' > script1.$$ +grep -cs "show service" script1.$$ >/dev/null +if [ $? -ne "0" ]; then + echo "list services: Failed" + failure=`expr $failure + 1` +else + passed=`expr $passed + 1` + echo "list services: Passed" +fi +maxadmin -pskysql script1.$$ | grep -cs 'Service' > /dev/null +if [ $? -ne "0" ]; then + echo "Show Service: Failed" + failure=`expr $failure + 1` +else + passed=`expr $passed + 1` + echo "Show Service: Passed" +fi +rm -f script1.$$ + + +maxadmin -pskysql list monitors | \ + awk -F\| '{ if (NF > 1) { sub(/ +$/, "", $1); printf("show monitor \"%s\"\n", $1); } }' > script1.$$ +grep -cs "show monitor" script1.$$ >/dev/null +if [ $? -ne "0" ]; then + echo "list monitors: Failed" + failure=`expr $failure + 1` +else + passed=`expr $passed + 1` + echo "list monitors: Passed" +fi +maxadmin -pskysql script1.$$ | grep -cs 'Monitor' > /dev/null +if [ $? -ne "0" ]; then + echo "Show Monitor: Failed" + failure=`expr $failure + 1` +else + passed=`expr $passed + 1` + echo "Show Monitor: Passed" +fi +rm -f script1.$$ + + +maxadmin -pskysql list sessions | \ + awk -F\| ' /^0x/ { if (NF > 1) { sub(/ +$/, "", $1); printf("show session \"%s\"\n", $1); } }' > script1.$$ +grep -cs "show session" script1.$$ >/dev/null +if [ $? -ne "0" ]; then + echo "list sessions: Failed" + failure=`expr $failure + 1` +else + passed=`expr $passed + 1` + echo "list sessions: Passed" +fi +maxadmin -pskysql script1.$$ | grep -cs 'Session' > /dev/null +if [ $? -ne "0" ]; then + echo "Show Session: Failed" + failure=`expr $failure + 1` +else + passed=`expr $passed + 1` + echo "Show Session: Passed" +fi +rm -f script1.$$ + + +maxadmin -pskysql list dcbs | \ + awk -F\| ' /^ 0x/ { if (NF > 1) { sub(/ +$/, "", $1); sub(/ 0x/, "0x", $1); printf("show dcb \"%s\"\n", $1); } }' > script1.$$ +grep -cs "show dcb" script1.$$ >/dev/null +if [ $? -ne "0" ]; then + echo "list dcbs: Failed" + failure=`expr $failure + 1` +else + passed=`expr $passed + 1` + echo "list dcbs: Passed" +fi +maxadmin -pskysql script1.$$ | grep -cs 'DCB' > /dev/null +if [ $? -ne "0" ]; then + echo "Show DCB: Failed" + failure=`expr $failure + 1` +else + passed=`expr $passed + 1` + echo "Show DCB: Passed" +fi +rm -f script1.$$ + + +maxadmin -pskysql list services | \ + awk -F\| '{ if (NF > 1) { sub(/ +$/, "", $1); printf("show dbusers \"%s\"\n", $1); } }' > script1.$$ +grep -cs "show dbusers" script1.$$ >/dev/null +if [ $? -ne "0" ]; then + echo "list services: Failed" + failure=`expr $failure + 1` +else + passed=`expr $passed + 1` + echo "list services: Passed" +fi +maxadmin -pskysql script1.$$ | grep -cs 'Users table data' > /dev/null +if [ $? -ne "0" ]; then + echo "Show dbusers: Failed" + failure=`expr $failure + 1` +else + passed=`expr $passed + 1` + echo "Show dbusers: Passed" +fi +rm -f script1.$$ + + echo "Test run complete. $passed passes, $failure failures" exit $failure diff --git a/debian/changelog b/debian/changelog index e416d995a..846f67a10 100644 --- a/debian/changelog +++ b/debian/changelog @@ -2,9 +2,9 @@ maxscale (1.0-beta) UNRELEASED; urgency=low * Beta release - -- Timofey Turenko Fri, 05 Jul 2014 14:00:00 +0200 + -- Timofey Turenko Fri, 05 Jul 2014 14:00:00 +0200 maxscale (0.7-1) UNRELEASED; urgency=low * Initial release. (Closes: #XXXXXX) - -- Timofey Turenko Tue, 11 Mar 2014 22:59:35 +0200 + -- Timofey Turenko Tue, 11 Mar 2014 22:59:35 +0200 diff --git a/log_manager/log_manager.cc b/log_manager/log_manager.cc index cb5e220cd..0d32b0354 100644 --- a/log_manager/log_manager.cc +++ b/log_manager/log_manager.cc @@ -270,12 +270,14 @@ static void blockbuf_register(blockbuf_t* bb); static void blockbuf_unregister(blockbuf_t* bb); static bool logfile_set_enabled(logfile_id_t id, bool val); static char* add_slash(char* str); -static bool file_exists_and_is_writable(char* filename, bool* writable); + +static bool check_file_and_path( + char* filename, + bool* nameconflict, + bool* writable); + static bool file_is_symlink(char* filename); - - - const char* get_suffix_default(void) { return ".log"; @@ -356,11 +358,6 @@ static bool logmanager_init_nomutex( fw = &lm->lm_filewriter; fn->fn_state = UNINIT; fw->fwr_state = UNINIT; - - /** - * Set global variable - */ - lm_enabled_logfiles_bitmask = lm->lm_enabled_logfiles; /** Initialize configuration including log file naming info */ if (!fnames_conf_init(fn, argc, argv)) { @@ -368,14 +365,23 @@ static bool logmanager_init_nomutex( } /** Initialize logfiles */ - if(!logfiles_init(lm)) { - goto return_succp; + if(!logfiles_init(lm)) + { + err = 1; + goto return_succp; } - /** Initialize filewriter data and open the (first) log file(s) + /** + * Set global variable + */ + lm_enabled_logfiles_bitmask = lm->lm_enabled_logfiles; + + /** Initialize filewriter data and open the (first) log file(s) * for each log file type. */ - if (!filewriter_init(lm, fw, lm->lm_clientmes, lm->lm_logmes)) { - goto return_succp; + if (!filewriter_init(lm, fw, lm->lm_clientmes, lm->lm_logmes)) + { + err = 1; + goto return_succp; } /** Initialize and start filewriter thread */ @@ -383,8 +389,9 @@ static bool logmanager_init_nomutex( thr_filewriter_fun, (void *)fw); - if ((err = skygw_thread_start(fw->fwr_thread)) != 0) { - goto return_succp; + if ((err = skygw_thread_start(fw->fwr_thread)) != 0) + { + goto return_succp; } /** Wait message from filewriter_thr */ skygw_message_wait(fw->fwr_clientmes); @@ -393,10 +400,11 @@ static bool logmanager_init_nomutex( lm->lm_enabled = true; return_succp: - if (err != 0) { + if (err != 0) + { /** This releases memory of all created objects */ logmanager_done_nomutex(); - fprintf(stderr, "* Initializing logmanager failed.\n"); + fprintf(stderr, "*\n* Error : Initializing log manager failed.\n*\n"); } return succp; } @@ -1769,7 +1777,7 @@ static bool logfiles_init( write_syslog); if (!succp) { - fprintf(stderr, "Initializing logfiles failed\n"); + fprintf(stderr, "*\n* Error : Initializing log files failed.\n"); break; } lid <<= 1; @@ -1917,10 +1925,11 @@ static char* add_slash( return str; } -/** - * @node Check if the file exists in the local file system and if it does, - * whether it is writable. - * + +/** + * @node Check if the path and file exist in the local file system and if they do, + * check if they are accessible and writable. + * * Parameters: * @param filename - * @@ -1928,55 +1937,91 @@ static char* add_slash( * @param writable - * * - * @return + * @return true & writable if file exists and it is writable, + * true & not writable if file exists but it can't be written, + * false & writable if file doesn't exist but directory could be written, and + * false & not writable if directory can't be written. * - * - * @details Note, that an space character is written to the end of file. + * @details Note, that a space character is written to the end of file. * TODO: recall what was the reason for not succeeding with simply * calling access, and fstat. vraa 26.11.13 - * */ -static bool file_exists_and_is_writable( - char* filename, - bool* writable) +static bool check_file_and_path( + char* filename, + bool* writable) { - int fd; - bool exists = true; - - if (filename == NULL) - { - exists = false; - } - else - { - fd = open(filename, O_CREAT|O_EXCL, S_IRWXU); - - /** file exist */ - if (fd == -1) - { - /** Open file and write a byte for test */ - fd = open(filename, O_CREAT|O_RDWR, S_IRWXU|S_IRWXG); - - if (fd != -1) - { - char c = ' '; - if (write(fd, &c, 1) == 1) - { - *writable = true; - } - close(fd); - } - } - else - { - close(fd); - unlink(filename); - exists = false; - } - } - return exists; + int fd; + bool exists; + + if (filename == NULL) + { + exists = false; + *writable = false; + } + else + { + fd = open(filename, O_CREAT|O_EXCL, S_IRWXU); + + if (fd == -1) + { + /** File exists, check permission to read/write */ + if (errno == EEXIST) + { + /** Open file and write a byte for test */ + fd = open(filename, O_CREAT|O_RDWR, S_IRWXU|S_IRWXG); + + if (fd == -1) + { + fprintf(stderr, + "*\n* Error : Can't access %s due " + "to %s.\n", + filename, + strerror(errno)); + *writable = false; + } + else + { + char c = ' '; + if (write(fd, &c, 1) == 1) + { + *writable = true; + } + else + { + fprintf(stderr, + "*\n* Error : Can't write to " + "%s due to %s.\n", + filename, + strerror(errno)); + *writable = false; + } + close(fd); + } + exists = true; + } + else + { + fprintf(stderr, + "*\n* Error : Can't access %s due to %s.\n", + filename, + strerror(errno)); + exists = false; + *writable = false; + } + } + else + { + close(fd); + unlink(filename); + exists = false; + *writable = true; + } + } + return exists; } + + static bool file_is_symlink( char* filename) { @@ -2112,7 +2157,8 @@ static bool logfile_init( logfile->lf_full_file_name = form_full_file_name(strparts, logfile->lf_name_seqno, 2); - if (store_shmem) { + if (store_shmem) + { strparts[0].sp_string = logfile->lf_linkpath; /** * Create name for link file @@ -2121,17 +2167,7 @@ static bool logfile_init( form_full_file_name(strparts, logfile->lf_name_seqno, 2); - fprintf(stderr, "%s\t: %s->%s\n", - STRLOGNAME(logfile_id), - logfile->lf_full_link_name, - logfile->lf_full_file_name); } - else - { - fprintf(stderr, "%s\t: %s\n", - STRLOGNAME(logfile_id), - logfile->lf_full_file_name); - } /** * At least one of the files couldn't be created. Increase * sequence number and retry until succeeds. @@ -2147,31 +2183,57 @@ static bool logfile_init( * If file exists but is different type, create fails and * new, increased sequence number is added to file name. */ - if (file_exists_and_is_writable(logfile->lf_full_file_name, - &writable)) - { - if (!writable || - file_is_symlink(logfile->lf_full_file_name)) - { - nameconflicts = true; - goto file_create_fail; - } - } - - if (store_shmem) - { - writable = false; + if (check_file_and_path( + logfile->lf_full_file_name, + &writable)) + { + /** Found similarly named file which isn't writable */ + if (!writable || + file_is_symlink(logfile->lf_full_file_name)) + { + nameconflicts = true; + goto file_create_fail; + } + } + else + { + /** + * Opening the file failed for some other reason than + * existing non-writable file. Shut down. + */ + if (!writable) + { + succp = false; + goto return_with_succp; + } + } - if (file_exists_and_is_writable( - logfile->lf_full_link_name, - &writable)) - { - if (!writable || - !file_is_symlink(logfile->lf_full_link_name)) - { - unlink(logfile->lf_full_link_name); - } - } + if (store_shmem) + { + if (check_file_and_path( + logfile->lf_full_file_name, + &writable)) + { + /** Found similarly named file which isn't writable */ + if (!writable || + file_is_symlink(logfile->lf_full_file_name)) + { + unlink(logfile->lf_full_file_name); + nameconflicts = true; + } + } + else + { + /** + * Opening the file failed for some other reason than + * existing non-writable file. Shut down. + */ + if (!writable) + { + succp = false; + goto return_with_succp; + } + } } file_create_fail: if (namecreatefail || nameconflicts) @@ -2188,7 +2250,6 @@ file_create_fail: free(logfile->lf_full_link_name); logfile->lf_full_link_name = NULL; } - goto return_with_succp; } } while (namecreatefail || nameconflicts); /** @@ -2202,11 +2263,24 @@ file_create_fail: MAXNBLOCKBUFS) == NULL) { ss_dfprintf(stderr, - "Initializing logfile blockbuf list " - "failed\n"); + "*\n* Error : Initializing buffers for log files " + "failed."); logfile_free_memory(logfile); goto return_with_succp; } + if (store_shmem) + { + fprintf(stderr, "%s\t: %s->%s\n", + STRLOGNAME(logfile_id), + logfile->lf_full_link_name, + logfile->lf_full_file_name); + } + else + { + fprintf(stderr, "%s\t: %s\n", + STRLOGNAME(logfile_id), + logfile->lf_full_file_name); + } succp = true; logfile->lf_state = RUN; CHK_LOGFILE(logfile); @@ -2244,12 +2318,18 @@ static void logfile_done( { switch(lf->lf_state) { case RUN: - CHK_LOGFILE(lf); - ss_dassert(lf->lf_npending_writes == 0); + CHK_LOGFILE(lf); + ss_dassert(lf->lf_npending_writes == 0); + /** fallthrough */ case INIT: - mlist_done(&lf->lf_blockbuf_list); - logfile_free_memory(lf); - lf->lf_state = DONE; + /** Test if list is initialized before freeing it */ + if (lf->lf_blockbuf_list.mlist_versno != 0) + { + mlist_done(&lf->lf_blockbuf_list); + } + logfile_free_memory(lf); + lf->lf_state = DONE; + /** fallthrough */ case DONE: case UNINIT: default: diff --git a/macros.cmake b/macros.cmake index cc29a5e09..d8f1b7827 100644 --- a/macros.cmake +++ b/macros.cmake @@ -1,9 +1,15 @@ +function(debugmsg MSG) + if(DEBUG_OUTPUT) + message(STATUS "DEBUG: ${MSG}") + endif() +endfunction() + macro(set_maxscale_version) #MaxScale version number set(MAXSCALE_VERSION_MAJOR "1") set(MAXSCALE_VERSION_MINOR "0") - set(MAXSCALE_VERSION_PATCH "1") + set(MAXSCALE_VERSION_PATCH "2") set(MAXSCALE_VERSION_NUMERIC "${MAXSCALE_VERSION_MAJOR}.${MAXSCALE_VERSION_MINOR}.${MAXSCALE_VERSION_PATCH}") set(MAXSCALE_VERSION "${MAXSCALE_VERSION_MAJOR}.${MAXSCALE_VERSION_MINOR}.${MAXSCALE_VERSION_PATCH}-beta") @@ -57,11 +63,12 @@ endmacro() macro(check_deps) + # Check for libraries MaxScale depends on set(MAXSCALE_DEPS aio ssl crypt crypto z m dl rt pthread) foreach(lib ${MAXSCALE_DEPS}) find_library(lib${lib} ${lib}) - if((DEFINED lib${lib}) AND (${lib${lib}} STREQUAL "lib${lib}-NOTFOUND")) + if((DEFINED lib${lib}) AND (${lib${lib}} MATCHES "NOTFOUND")) set(DEPS_ERROR TRUE) set(FAILED_DEPS "${FAILED_DEPS} lib${lib}") elseif(DEBUG_OUTPUT) @@ -82,27 +89,29 @@ macro(check_dirs) set(DEPS_OK TRUE CACHE BOOL "If all the dependencies were found.") # Find the MySQL headers if they were not defined + if(DEFINED MYSQL_DIR) - if(DEBUG_OUTPUT) - message(STATUS "Searching for MySQL headers at: ${MYSQL_DIR}") - endif() + debugmsg("Searching for MySQL headers at: ${MYSQL_DIR}") find_path(MYSQL_DIR_LOC mysql.h PATHS ${MYSQL_DIR} PATH_SUFFIXES mysql mariadb NO_DEFAULT_PATH) + else() + find_path(MYSQL_DIR_LOC mysql.h PATH_SUFFIXES mysql mariadb) endif() - find_path(MYSQL_DIR_LOC mysql.h PATH_SUFFIXES mysql mariadb) - if(DEBUG_OUTPUT) - message(STATUS "Search returned: ${MYSQL_DIR_LOC}") - endif() - if(${MYSQL_DIR_LOC} STREQUAL "MYSQL_DIR_LOC-NOTFOUND") + +debugmsg("Search returned: ${MYSQL_DIR_LOC}") + + if(${MYSQL_DIR_LOC} MATCHES "NOTFOUND") set(DEPS_OK FALSE CACHE BOOL "If all the dependencies were found.") message(FATAL_ERROR "Fatal Error: MySQL headers were not found.") else() - message(STATUS "Using MySQL headers found at: ${MYSQL_DIR}") set(MYSQL_DIR ${MYSQL_DIR_LOC} CACHE PATH "Path to MySQL headers" FORCE) + message(STATUS "Using MySQL headers found at: ${MYSQL_DIR}") endif() - set(MYSQL_DIR_LOC "" INTERNAL) + + unset(MYSQL_DIR_LOC) # Find the errmsg.sys file if it was not defied if( DEFINED ERRMSG ) + debugmsg("Looking for errmsg.sys at: ${ERRMSG}") find_file(ERRMSG_FILE errmsg.sys PATHS ${ERRMSG} NO_DEFAULT_PATH) endif() find_file(ERRMSG_FILE errmsg.sys PATHS /usr/share/mysql /usr/local/share/mysql PATH_SUFFIXES english) @@ -113,48 +122,62 @@ macro(check_dirs) message(STATUS "Using errmsg.sys found at: ${ERRMSG_FILE}") endif() set(ERRMSG ${ERRMSG_FILE} CACHE FILEPATH "Path to the errmsg.sys file." FORCE) - set(ERRMSG_FILE "" INTERNAL) + unset(ERRMSG_FILE) # Find the embedded mysql library - if(STATIC_EMBEDDED) + + if (DEFINED EMBEDDED_LIB) + if( NOT (IS_DIRECTORY ${EMBEDDED_LIB}) ) + debugmsg("EMBEDDED_LIB is not a directory: ${EMBEDDED_LIB}") + if(${CMAKE_VERSION} VERSION_LESS 2.12 ) + set(COMP_VAR PATH) + else() + set(COMP_VAR DIRECTORY) + endif() + get_filename_component(EMBEDDED_LIB ${EMBEDDED_LIB} ${COMP_VAR}) + debugmsg("EMBEDDED_LIB directory component: ${EMBEDDED_LIB}") + endif() + debugmsg("Searching for the embedded library at: ${EMBEDDED_LIB}") + endif() + if(STATIC_EMBEDDED) + + debugmsg("Using the static embedded library...") set(OLD_SUFFIXES ${CMAKE_FIND_LIBRARY_SUFFIXES}) set(CMAKE_FIND_LIBRARY_SUFFIXES ".a") if (DEFINED EMBEDDED_LIB) - if(DEBUG_OUTPUT) - message(STATUS "Searching for libmysqld.a at: ${EMBEDDED_LIB}") - endif() + debugmsg("Searching for libmysqld.a at: ${EMBEDDED_LIB}") find_library(EMBEDDED_LIB_STATIC libmysqld.a PATHS ${EMBEDDED_LIB} PATH_SUFFIXES mysql mariadb NO_DEFAULT_PATH) else() find_library(EMBEDDED_LIB_STATIC libmysqld.a PATH_SUFFIXES mysql mariadb) endif() - if(DEBUG_OUTPUT) - message(STATUS "Search returned: ${EMBEDDED_LIB_STATIC}") - endif() + debugmsg("Search returned: ${EMBEDDED_LIB_STATIC}") + set(EMBEDDED_LIB ${EMBEDDED_LIB_STATIC} CACHE FILEPATH "Path to libmysqld" FORCE) set(CMAKE_FIND_LIBRARY_SUFFIXES ${OLD_SUFFIXES}) - set(OLD_SUFFIXES "" INTERNAL) - else() + else() + debugmsg("Using the dynamic embedded library...") + set(OLD_SUFFIXES ${CMAKE_FIND_LIBRARY_SUFFIXES}) + set(CMAKE_FIND_LIBRARY_SUFFIXES ".so") if (DEFINED EMBEDDED_LIB) - if(DEBUG_OUTPUT) - message(STATUS "Searching for libmysqld.so at: ${EMBEDDED_LIB}") - endif() + debugmsg("Searching for libmysqld.so at: ${EMBEDDED_LIB}") find_library(EMBEDDED_LIB_DYNAMIC mysqld PATHS ${EMBEDDED_LIB} PATH_SUFFIXES mysql mariadb NO_DEFAULT_PATH) else() find_library(EMBEDDED_LIB_DYNAMIC mysqld PATH_SUFFIXES mysql mariadb) endif() - if(DEBUG_OUTPUT) - message(STATUS "Search returned: ${EMBEDDED_LIB_DYNAMIC}") - endif() + debugmsg("Search returned: ${EMBEDDED_LIB_DYNAMIC}") set(EMBEDDED_LIB ${EMBEDDED_LIB_DYNAMIC} CACHE FILEPATH "Path to libmysqld" FORCE) - + set(CMAKE_FIND_LIBRARY_SUFFIXES ${OLD_SUFFIXES}) + endif() - set(EMBEDDED_LIB_DYNAMIC "" INTERNAL) - set(EMBEDDED_LIB_STATIC "" INTERNAL) + + unset(EMBEDDED_LIB_DYNAMIC) + unset(EMBEDDED_LIB_STATIC) + unset(OLD_SUFFIXES) # Inform the user about the embedded library - if( (${EMBEDDED_LIB} STREQUAL "EMBEDDED_LIB_STATIC-NOTFOUND") OR (${EMBEDDED_LIB} STREQUAL "EMBEDDED_LIB_DYNAMIC-NOTFOUND")) + if( (${EMBEDDED_LIB} MATCHES "NOTFOUND") OR (${EMBEDDED_LIB} MATCHES "NOTFOUND")) set(DEPS_OK FALSE CACHE BOOL "If all the dependencies were found.") message(FATAL_ERROR "Library not found: libmysqld. If your install of MySQL is in a non-default location, please provide the location with -DEMBEDDED_LIB=") else() @@ -176,17 +199,19 @@ macro(check_dirs) else() set(DEB_BASED FALSE CACHE BOOL "If init.d script uses /lib/lsb/init-functions instead of /etc/rc.d/init.d/functions.") endif() - set(DEB_FNC "" INTERNAL) - set(RPM_FNC "" INTERNAL) + unset(DEB_FNC) + unset(RPM_FNC) #Check RabbitMQ headers and libraries if(BUILD_RABBITMQ) + include(CheckCSourceCompiles) if(DEFINED RABBITMQ_LIB) find_library(RMQ_LIB rabbitmq PATHS ${RABBITMQ_LIB} NO_DEFAULT_PATH) + else() + find_library(RMQ_LIB rabbitmq) endif() - find_library(RMQ_LIB rabbitmq) - if(RMQ_LIB STREQUAL "RMQ_LIB-NOTFOUND") + if(RMQ_LIB MATCHES "NOTFOUND") set(DEPS_OK FALSE CACHE BOOL "If all the dependencies were found.") message(FATAL_ERROR "Cannot find RabbitMQ libraries, please define the path to the libraries with -DRABBITMQ_LIB=") else() @@ -196,16 +221,22 @@ macro(check_dirs) if(DEFINED RABBITMQ_HEADERS) find_file(RMQ_HEADERS amqp.h PATHS ${RABBITMQ_HEADERS} NO_DEFAULT_PATH) + else() + find_file(RMQ_HEADERS amqp.h) endif() - find_file(RMQ_HEADERS amqp.h) - if(RMQ_HEADERS STREQUAL "RMQ_HEADERS-NOTFOUND") + if(RMQ_HEADERS MATCHES "NOTFOUND") set(DEPS_OK FALSE CACHE BOOL "If all the dependencies were found.") message(FATAL_ERROR "Cannot find RabbitMQ headers, please define the path to the headers with -DRABBITMQ_HEADERS=") else() set(RABBITMQ_HEADERS ${RMQ_HEADERS} CACHE PATH "Path to RabbitMQ headers" FORCE) message(STATUS "Using RabbitMQ headers found at: ${RABBITMQ_HEADERS}") endif() - + set(CMAKE_REQUIRED_INCLUDES ${RABBITMQ_HEADERS}) + check_c_source_compiles("#include \n int main(){if(AMQP_DELIVERY_PERSISTENT){return 0;}return 1;}" HAVE_RMQ50) + if(NOT HAVE_RMQ50) + message(FATAL_ERROR "Old version of RabbitMQ-C library found. Version 0.5 or newer is required.") + endif() + endif() endmacro() @@ -224,4 +255,4 @@ endif() endforeach() list(REMOVE_DUPLICATES ALLDIRS) set(${VAR} "${ALLDIRS}" CACHE PATH " " FORCE) -endfunction() \ No newline at end of file +endfunction() diff --git a/query_classifier/query_classifier.h b/query_classifier/query_classifier.h index db2011642..3600bce5a 100644 --- a/query_classifier/query_classifier.h +++ b/query_classifier/query_classifier.h @@ -18,6 +18,7 @@ Copyright MariaDB Corporation Ab */ /** getpid */ +#include #include #include #include diff --git a/query_classifier/test/canonical_tests/canonizer.c b/query_classifier/test/canonical_tests/canonizer.c index 7e33fe4a1..bffe9c1b9 100644 --- a/query_classifier/test/canonical_tests/canonizer.c +++ b/query_classifier/test/canonical_tests/canonizer.c @@ -1,3 +1,4 @@ +#include #include #include #include diff --git a/query_classifier/test/classify.c b/query_classifier/test/classify.c index 8eafbdc5c..4fe33a68b 100644 --- a/query_classifier/test/classify.c +++ b/query_classifier/test/classify.c @@ -1,3 +1,4 @@ +#include #include #include #include @@ -8,7 +9,7 @@ #include static char* server_options[] = { - "SkySQL Gateway", + "MariaDB Corporation MaxScale", "--no-defaults", "--datadir=.", "--language=.", diff --git a/replication_listener/access_method_factory.cpp b/replication_listener/access_method_factory.cpp index 7261b9355..b44f69692 100644 --- a/replication_listener/access_method_factory.cpp +++ b/replication_listener/access_method_factory.cpp @@ -26,7 +26,7 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA MariaDB Corporation change details: - Removed unnecessary file driver -Author: Jan Lindström (jan.lindstrom@skysql.com +Author: Jan Lindström (jan.lindstrom@mariadb.com */ #include "access_method_factory.h" diff --git a/replication_listener/basic_content_handler.cpp b/replication_listener/basic_content_handler.cpp index 9b209ab28..ffcc35fde 100644 --- a/replication_listener/basic_content_handler.cpp +++ b/replication_listener/basic_content_handler.cpp @@ -26,7 +26,7 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA MariaDB Corporation change details: - Added GTID event handler -Author: Jan Lindström (jan.lindstrom@skysql.com +Author: Jan Lindström (jan.lindstrom@mariadb.com */ diff --git a/replication_listener/basic_content_handler.h b/replication_listener/basic_content_handler.h index 5debfb672..7a83838af 100644 --- a/replication_listener/basic_content_handler.h +++ b/replication_listener/basic_content_handler.h @@ -26,7 +26,7 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA MariaDB Corporation change details: - Added GTID event handler -Author: Jan Lindström (jan.lindstrom@skysql.com +Author: Jan Lindström (jan.lindstrom@mariadb.com */ diff --git a/replication_listener/binary_log.cpp b/replication_listener/binary_log.cpp index 199cf65c4..20c87c896 100644 --- a/replication_listener/binary_log.cpp +++ b/replication_listener/binary_log.cpp @@ -27,7 +27,7 @@ MariaDB Corporation change details: - Added support for setting binlog position based on GTID - Added support for MySQL and MariDB server types -Author: Jan Lindström (jan.lindstrom@skysql.com +Author: Jan Lindström (jan.lindstrom@mariadb.com */ diff --git a/replication_listener/binlog_api.h b/replication_listener/binlog_api.h index fb6e24f77..33d32fd1d 100644 --- a/replication_listener/binlog_api.h +++ b/replication_listener/binlog_api.h @@ -27,7 +27,7 @@ MariaDB Corporation change details: - Added support for setting binlog position based on GTID - Added support for MySQL and MariDB server types -Author: Jan Lindström (jan.lindstrom@skysql.com +Author: Jan Lindström (jan.lindstrom@mariadb.com */ diff --git a/replication_listener/binlog_driver.cpp b/replication_listener/binlog_driver.cpp index 86c3ea954..81c019332 100644 --- a/replication_listener/binlog_driver.cpp +++ b/replication_listener/binlog_driver.cpp @@ -26,7 +26,7 @@ MariaDB Corporation change details: - Added support for GTID event handling for both MySQL and MariaDB -Author: Jan Lindström (jan.lindstrom@skysql.com +Author: Jan Lindström (jan.lindstrom@mariadb.com */ diff --git a/replication_listener/binlog_driver.h b/replication_listener/binlog_driver.h index 73e60587d..44f9fb3c4 100644 --- a/replication_listener/binlog_driver.h +++ b/replication_listener/binlog_driver.h @@ -27,7 +27,7 @@ MariaDB Corporation change details: - Added support for GTID event handling for both MySQL and MariaDB - Added support for setting binlog position based on GTID -Author: Jan Lindström (jan.lindstrom@skysql.com +Author: Jan Lindström (jan.lindstrom@mariadb.com */ diff --git a/replication_listener/binlog_event.cpp b/replication_listener/binlog_event.cpp index d1f4da802..d89142333 100644 --- a/replication_listener/binlog_event.cpp +++ b/replication_listener/binlog_event.cpp @@ -26,7 +26,7 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA MariaDB Corporation change details: - Added support for GTID event handling for both MySQL and MariaDB -Author: Jan Lindström (jan.lindstrom@skysql.com +Author: Jan Lindström (jan.lindstrom@mariadb.com */ diff --git a/replication_listener/binlog_event.h b/replication_listener/binlog_event.h index 3c8285044..45aa31a83 100644 --- a/replication_listener/binlog_event.h +++ b/replication_listener/binlog_event.h @@ -26,7 +26,7 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA MariaDB Corporation change details: - Added support for GTID event handling for both MySQL and MariaDB -Author: Jan Lindström (jan.lindstrom@skysql.com +Author: Jan Lindström (jan.lindstrom@mariadb.com */ #ifndef _BINLOG_EVENT_H diff --git a/replication_listener/gtid.cpp b/replication_listener/gtid.cpp index ed9d80bea..7091dfc92 100644 --- a/replication_listener/gtid.cpp +++ b/replication_listener/gtid.cpp @@ -16,7 +16,7 @@ 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. -Author: Jan Lindström jan.lindstrom@skysql.com +Author: Jan Lindström jan.lindstrom@mariadb.com */ diff --git a/replication_listener/gtid.h b/replication_listener/gtid.h index 359ae9d04..218e2a30f 100644 --- a/replication_listener/gtid.h +++ b/replication_listener/gtid.h @@ -15,7 +15,7 @@ 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. -Author: Jan Lindström jan.lindstrom@skysql.com +Author: Jan Lindström jan.lindstrom@mariadb.com */ diff --git a/replication_listener/listener_exception.h b/replication_listener/listener_exception.h index 7ff656ea8..b38312b58 100644 --- a/replication_listener/listener_exception.h +++ b/replication_listener/listener_exception.h @@ -16,7 +16,7 @@ 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. -Author: Jan Lindström jan.lindstrom@skysql.com +Author: Jan Lindström jan.lindstrom@mariadb.com */ diff --git a/replication_listener/protocol.cpp b/replication_listener/protocol.cpp index 8d07f6877..317500ce8 100644 --- a/replication_listener/protocol.cpp +++ b/replication_listener/protocol.cpp @@ -26,7 +26,7 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA MariaDB Corporation change details: - Added support for GTID event handling for both MySQL and MariaDB -Author: Jan Lindström (jan.lindstrom@skysql.com +Author: Jan Lindström (jan.lindstrom@mariadb.com */ #include diff --git a/replication_listener/tcp_driver.cpp b/replication_listener/tcp_driver.cpp index 216077249..a0aa88986 100644 --- a/replication_listener/tcp_driver.cpp +++ b/replication_listener/tcp_driver.cpp @@ -28,7 +28,7 @@ MariaDB Corporation change details: - Added support for starting binlog dump from GTID position - Added error handling using exceptions -Author: Jan Lindström (jan.lindstrom@skysql.com +Author: Jan Lindström (jan.lindstrom@mariadb.com */ #include "binlog_api.h" diff --git a/replication_listener/tcp_driver.h b/replication_listener/tcp_driver.h index 7d4d96c94..530249276 100644 --- a/replication_listener/tcp_driver.h +++ b/replication_listener/tcp_driver.h @@ -28,7 +28,7 @@ MariaDB Corporation change details: - Added support for starting binlog dump from GTID position - Added support for MariaDB server -Author: Jan Lindström (jan.lindstrom@skysql.com +Author: Jan Lindström (jan.lindstrom@mariadb.com */ diff --git a/replication_listener/tests/event_dump.cpp b/replication_listener/tests/event_dump.cpp index d9c415374..132ba6f8b 100644 --- a/replication_listener/tests/event_dump.cpp +++ b/replication_listener/tests/event_dump.cpp @@ -16,7 +16,7 @@ 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. -Author: Jan Lindström jan.lindstrom@skysql.com +Author: Jan Lindström jan.lindstrom@mariadb.com */ diff --git a/server/CMakeLists.txt b/server/CMakeLists.txt index a42c625ae..6cd174190 100644 --- a/server/CMakeLists.txt +++ b/server/CMakeLists.txt @@ -1,6 +1,3 @@ add_subdirectory(core) add_subdirectory(modules) add_subdirectory(inih) -if(BUILD_TESTS) -add_subdirectory(test) -endif() \ No newline at end of file diff --git a/server/core/buffer.c b/server/core/buffer.c index 46315cf69..9ee13c87f 100644 --- a/server/core/buffer.c +++ b/server/core/buffer.c @@ -1,5 +1,5 @@ /* - * This file is distributed as part of the SkySQL Gateway. It is free + * This file is distributed as part of the MariaDB Corporation MaxScale. It 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. @@ -13,11 +13,11 @@ * this program; if not, write to the Free Software Foundation, Inc., 51 * Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * - * Copyright SkySQL Ab 2013 + * Copyright MariaDB Corporation Ab 2014 */ /** - * @file buffer.h - The Gateway buffer management functions + * @file buffer.h - The MaxScale buffer management functions * * The buffer management is based on the principle of a linked list * of variable size buffer, the intention beign to allow longer diff --git a/server/core/config.c b/server/core/config.c index ead016000..181b009fc 100644 --- a/server/core/config.c +++ b/server/core/config.c @@ -41,6 +41,7 @@ * * @endverbatim */ +#include #include #include #include @@ -816,7 +817,7 @@ int error_count = 0; int found = 0; while (obj1) { - if (strcmp(s, obj1->object) == 0 && + if (strcmp(trim(s), obj1->object) == 0 && obj->element && obj1->element) { found = 1; @@ -1448,7 +1449,7 @@ SERVER *server; int found = 0; while (obj1) { - if (strcmp(s, obj1->object) == 0 && + if (strcmp(trim(s), obj1->object) == 0 && obj->element && obj1->element) { found = 1; diff --git a/server/core/dbusers.c b/server/core/dbusers.c index c65aafdc9..3b2b36361 100644 --- a/server/core/dbusers.c +++ b/server/core/dbusers.c @@ -28,6 +28,9 @@ * 06/02/2014 Massimiliano Pinto Mysql user root selected based on configuration flag * 26/02/2014 Massimiliano Pinto Addd: replace_mysql_users() routine may replace users' table based on a checksum * 28/02/2014 Massimiliano Pinto Added Mysql user@host authentication + * 29/09/2014 Massimiliano Pinto Added Mysql user@host authentication with wildcard in IPv4 hosts: + * x.y.z.%, x.y.%.%, x.%.%.% + * 03/10/14 Massimiliano Pinto Added netmask to user@host authentication for wildcard in IPv4 hosts * * @endverbatim */ @@ -50,13 +53,14 @@ extern int lm_enabled_logfiles_bitmask; -static int getUsers(SERVICE *service, struct users *users); +static int getUsers(SERVICE *service, USERS *users); static int uh_cmpfun( void* v1, void* v2); static void *uh_keydup(void* key); static void uh_keyfree( void* key); static int uh_hfun( void* key); char *mysql_users_fetch(USERS *users, MYSQL_USER_HOST *key); char *mysql_format_user_entry(void *data); +int add_mysql_users_with_host_ipv4(USERS *users, char *user, char *host, char *passwd); /** * Load the user/passwd form mysql.user table into the service users' hashtable @@ -82,7 +86,7 @@ int reload_mysql_users(SERVICE *service) { int i; -struct users *newusers, *oldusers; +USERS *newusers, *oldusers; if ((newusers = mysql_users_alloc()) == NULL) return 0; @@ -108,15 +112,17 @@ int replace_mysql_users(SERVICE *service) { int i; -struct users *newusers, *oldusers; +USERS *newusers, *oldusers; if ((newusers = mysql_users_alloc()) == NULL) return -1; i = getUsers(service, newusers); - if (i <= 0) + if (i <= 0) { + users_free(newusers); return i; + } spinlock_acquire(&service->spin); oldusers = service->users; @@ -148,6 +154,92 @@ struct users *newusers, *oldusers; return i; } + +/** + * Add a new MySQL user with host, password and netmask into the service users table + * + * The netmask values are: + * 0 for any, 32 for single IPv4 + * 24 for a class C from a.b.c.%, 16 for a Class B from a.b.%.% and 8 for a Class A from a.%.%.% + * + * @param users The users table + * @param user The user name + * @param host The host to add, with possible wildcards + * @param passwd The sha1(sha1(passoword)) to add + * @return 1 on success, 0 on failure + */ + +int add_mysql_users_with_host_ipv4(USERS *users, char *user, char *host, char *passwd) { + struct sockaddr_in serv_addr; + MYSQL_USER_HOST key; + char ret_ip[INET_ADDRSTRLEN + 1]=""; + int found_range=0; + int found_any=0; + int ret = 0; + + /* prepare the user@host data struct */ + memset(&serv_addr, 0, sizeof(serv_addr)); + memset(&key, 0, sizeof(key)); + + /* set user */ + key.user = strdup(user); + + if(key.user == NULL) { + return ret; + } + + /* handle ANY, Class C,B,A */ + + /* ANY */ + if (strcmp(host, "%") == 0) { + strcpy(ret_ip, "0.0.0.0"); + found_any = 1; + } else { + char *tmp; + strcpy(ret_ip, host); + tmp = ret_ip+strlen(ret_ip)-1; + + /* start from Class C */ + while(*tmp) { + if (*tmp == '%') { + /* set only the last IPv4 byte to 1 + * avoiding setipadress() failure + * for Class C address + */ + found_range++; + if (found_range == 1) + *tmp = '1'; + else + *tmp = '0'; + } + tmp--; + } + } + + /* fill IPv4 data struct */ + if (setipaddress(&serv_addr.sin_addr, ret_ip)) { + + /* copy IPv4 data into key.ipv4 */ + memcpy(&key.ipv4, &serv_addr, sizeof(serv_addr)); + + if (found_range) { + /* let's zero the last IP byte: a.b.c.0 we set above to 1*/ + key.ipv4.sin_addr.s_addr &= 0x00FFFFFF; + key.netmask = 32 - (found_range * 8); + } else { + key.netmask = 32 - (found_any * 32); + } + + /* add user@host as key and passwd as value in the MySQL users hash table */ + if (mysql_users_add(users, &key, passwd)) + ret = 1; + } + + free(key.user); + + return ret; +} + /** * Load the user/passwd form mysql.user table into the service users' hashtable * environment. @@ -157,7 +249,7 @@ struct users *newusers, *oldusers; * @return -1 on any error or the number of users inserted (0 means no users at all) */ static int -getUsers(SERVICE *service, struct users *users) +getUsers(SERVICE *service, USERS *users) { MYSQL *con = NULL; MYSQL_ROW row; @@ -173,8 +265,6 @@ getUsers(SERVICE *service, struct users *users) char *users_data = NULL; int nusers = 0; int users_data_row_len = MYSQL_USER_MAXLEN + MYSQL_HOST_MAXLEN + MYSQL_PASSWORD_LEN; - struct sockaddr_in serv_addr; - MYSQL_USER_HOST key; /* enable_root for MySQL protocol module means load the root user credentials from backend databases */ if(service->enable_root) { @@ -311,63 +401,26 @@ getUsers(SERVICE *service, struct users *users) * added to hashtable. */ - char ret_ip[INET_ADDRSTRLEN + 1]=""; - const char *rc; + int rc = 0; - /* prepare the user@host data struct */ - memset(&serv_addr, 0, sizeof(serv_addr)); - memset(&key, 0, sizeof(key)); + rc = add_mysql_users_with_host_ipv4(users, row[0], row[1], strlen(row[2]) ? row[2]+1 : row[2]); - /* if host == '%', 0 is passed */ - if (setipaddress(&serv_addr.sin_addr, strcmp(row[1], "%") ? row[1] : "0.0.0.0")) { + if (rc == 1) { + LOGIF(LD, (skygw_log_write_flush( + LOGFILE_DEBUG, + "%lu [mysql_users_add()] Added user %s@%s", + pthread_self(), + row[0], + row[1]))); - key.user = strdup(row[0]); - - if(key.user == NULL) { - LOGIF(LE, (skygw_log_write_flush( - LOGFILE_ERROR, - "%lu [getUsers()] strdup() failed for user %s", - pthread_self(), - row[0]))); - - continue; - } - - memcpy(&key.ipv4, &serv_addr, sizeof(serv_addr)); - - rc = inet_ntop(AF_INET, &(serv_addr).sin_addr, ret_ip, INET_ADDRSTRLEN); - - /* add user@host as key and passwd as value in the MySQL users hash table */ - if (mysql_users_add(users, &key, strlen(row[2]) ? row[2]+1 : row[2])) { - LOGIF(LD, (skygw_log_write_flush( - LOGFILE_DEBUG, - "%lu [mysql_users_add()] Added user %s@%s(%s)", - pthread_self(), - row[0], - row[1], - rc == NULL ? "NULL" : ret_ip))); - - /* Append data in the memory area for SHA1 digest */ - strncat(users_data, row[3], users_data_row_len); - - total_users++; - } else { - LOGIF(LE, (skygw_log_write_flush( - LOGFILE_ERROR, - "%lu [mysql_users_add()] Failed adding user %s@%s(%s)", - pthread_self(), - row[0], - row[1], - rc == NULL ? "NULL" : ret_ip))); - } - - free(key.user); + /* Append data in the memory area for SHA1 digest */ + strncat(users_data, row[3], users_data_row_len); + total_users++; } else { - /* setipaddress() failed, skip user add and log this*/ LOGIF(LE, (skygw_log_write_flush( LOGFILE_ERROR, - "%lu [getUsers()] setipaddress failed: user %s@%s not added", + "%lu [mysql_users_add()] Failed adding user %s@%s", pthread_self(), row[0], row[1]))); @@ -475,7 +528,7 @@ static int uh_hfun( void* key) { * Currently only IPv4 addresses are supported * * @param key1 The key value, i.e. username@host (IPv4) - * @param key1 The key value, i.e. username@host (IPv4) + * @param key2 The key value, i.e. username@host (IPv4) * @return The compare value */ @@ -486,7 +539,7 @@ static int uh_cmpfun( void* v1, void* v2) { if (v1 == NULL || v2 == NULL || hu1 == NULL || hu2 == NULL || hu1->user == NULL || hu2->user == NULL) return 0; - if (strcmp(hu1->user, hu2->user) == 0 && (hu1->ipv4.sin_addr.s_addr == hu2->ipv4.sin_addr.s_addr)) { + if (strcmp(hu1->user, hu2->user) == 0 && (hu1->ipv4.sin_addr.s_addr == hu2->ipv4.sin_addr.s_addr) && (hu1->netmask >= hu2->netmask)) { return 0; } else { return 1; @@ -513,6 +566,7 @@ static void *uh_keydup(void* key) { return NULL; memcpy(&rval->ipv4, ¤t_key->ipv4, sizeof(struct sockaddr_in)); + memcpy(&rval->netmask, ¤t_key->netmask, sizeof(int)); return (void *) rval; } @@ -561,13 +615,25 @@ char *mysql_format_user_entry(void *data) if (mysql_user == NULL) return NULL; - if (entry->ipv4.sin_addr.s_addr == INADDR_ANY) { - snprintf(mysql_user, mysql_user_len, "%s@%%", entry->user); - } else { + if (entry->ipv4.sin_addr.s_addr == INADDR_ANY && entry->netmask == 0) { + snprintf(mysql_user, mysql_user_len-1, "%s@%%", entry->user); + } else if ( (entry->ipv4.sin_addr.s_addr & 0xFF000000) == 0 && entry->netmask == 24) { + snprintf(mysql_user, mysql_user_len-1, "%s@%i.%i.%i.%%", entry->user, entry->ipv4.sin_addr.s_addr & 0x000000FF, (entry->ipv4.sin_addr.s_addr & 0x0000FF00) / (256), (entry->ipv4.sin_addr.s_addr & 0x00FF0000) / (256 * 256)); + } else if ( (entry->ipv4.sin_addr.s_addr & 0xFFFF0000) == 0 && entry->netmask == 16) { + snprintf(mysql_user, mysql_user_len-1, "%s@%i.%i.%%.%%", entry->user, entry->ipv4.sin_addr.s_addr & 0x000000FF, (entry->ipv4.sin_addr.s_addr & 0x0000FF00) / (256)); + } else if ( (entry->ipv4.sin_addr.s_addr & 0xFFFFFF00) == 0 && entry->netmask == 8) { + snprintf(mysql_user, mysql_user_len-1, "%s@%i.%%.%%.%%", entry->user, entry->ipv4.sin_addr.s_addr & 0x000000FF); + } else if (entry->netmask == 32) { strncpy(mysql_user, entry->user, MYSQL_USER_MAXLEN); strcat(mysql_user, "@"); inet_ntop(AF_INET, &(entry->ipv4).sin_addr, mysql_user+strlen(mysql_user), INET_ADDRSTRLEN); + } else { + snprintf(mysql_user, MYSQL_USER_MAXLEN-6, "warn: %s", entry->user); + strcat(mysql_user, "@"); + inet_ntop(AF_INET, &(entry->ipv4).sin_addr, mysql_user+strlen(mysql_user), INET_ADDRSTRLEN); + } return mysql_user; } + diff --git a/server/core/gateway.c b/server/core/gateway.c index 2749850fe..58a7153e5 100644 --- a/server/core/gateway.c +++ b/server/core/gateway.c @@ -40,6 +40,7 @@ * @endverbatim */ #define _XOPEN_SOURCE 700 +#include #include #include #include @@ -72,7 +73,9 @@ #include /** for procname */ -#define _GNU_SOURCE +#if !defined(_GNU_SOURCE) +# define _GNU_SOURCE +#endif extern char *program_invocation_name; extern char *program_invocation_short_name; @@ -173,6 +176,9 @@ static bool resolve_maxscale_conf_fname( char* cnf_file_arg); static bool resolve_maxscale_homedir( char** p_home_dir); + +static char* check_dir_access(char* dirname); + /** * Handler for SIGHUP signal. Reload the configuration for the * gateway. @@ -533,7 +539,7 @@ return_succp: static bool resolve_maxscale_homedir( char** p_home_dir) { - bool succp = false; + bool succp; char* tmp; char* log_context = NULL; @@ -592,65 +598,55 @@ static bool resolve_maxscale_homedir( if (*p_home_dir != NULL) { log_context = strdup("Current working directory"); - goto check_home_dir; } check_home_dir: - if (*p_home_dir != NULL) - { - if (!file_is_readable(*p_home_dir)) - { - char* tailstr = "MaxScale doesn't have read permission " - "to MAXSCALE_HOME."; - char* logstr = (char*)malloc(strlen(log_context)+ - 1+ - strlen(tailstr)+ - 1); - snprintf(logstr, - strlen(log_context)+ - 1+ - strlen(tailstr)+1, - "%s:%s", - log_context, - tailstr); - print_log_n_stderr(true, true, logstr, logstr, 0); - free(logstr); - goto return_succp; - } - - if (!file_is_writable(*p_home_dir)) - { - char* tailstr = "MaxScale doesn't have write permission " - "to MAXSCALE_HOME. Exiting."; - char* logstr = (char*)malloc(strlen(log_context)+ - 1+ - strlen(tailstr)+ - 1); - snprintf(logstr, - strlen(log_context)+ - 1+ - strlen(tailstr)+1, - "%s:%s", - log_context, - tailstr); - print_log_n_stderr(true, true, logstr, logstr, 0); - free(logstr); - goto return_succp; - } - - if (!daemon_mode) - { - fprintf(stderr, - "Using %s as MAXSCALE_HOME = %s\n", - log_context, - tmp); - } - succp = true; - goto return_succp; - } - -return_succp: - free (tmp); + + if (*p_home_dir != NULL) + { + char* errstr; + + errstr = check_dir_access(*p_home_dir); + + if (errstr != NULL) + { + char* logstr = (char*)malloc(strlen(log_context)+ + 1+ + strlen(errstr)+ + 1); + + snprintf(logstr, + strlen(log_context)+ + 1+ + strlen(errstr)+1, + "%s: %s", + log_context, + errstr); + + print_log_n_stderr(true, true, logstr, logstr, 0); + + free(errstr); + free(logstr); + succp = false; + } + else + { + succp = true; + + if (!daemon_mode) + { + fprintf(stderr, + "Using %s as MAXSCALE_HOME = %s\n", + log_context, + tmp); + } + } + } + else + { + succp = false; + } + free (tmp); if (log_context != NULL) { @@ -667,6 +663,42 @@ return_succp: return succp; } +/** + * Check read and write accessibility to a directory. + * @param dirname directory to be checked + * + * @return NULL if directory can be read and written, an error message if either + * read or write is not permitted. + */ +static char* check_dir_access( + char* dirname) +{ + char* errstr = NULL; + + if (dirname == NULL) + { + errstr = strdup("Directory argument is NULL"); + goto retblock; + } + + if (!file_is_readable(dirname)) + { + errstr = strdup("MaxScale doesn't have read permission " + "to MAXSCALE_HOME."); + goto retblock; + } + + if (!file_is_writable(dirname)) + { + errstr = strdup("MaxScale doesn't have write permission " + "to MAXSCALE_HOME. Exiting."); + goto retblock; + } + +retblock: + return errstr; +} + /** * @node Provides error printing for non-formatted error strings. @@ -1370,13 +1402,51 @@ int main(int argc, char **argv) { if (!resolve_maxscale_homedir(&home_dir)) { - ss_dassert(home_dir == NULL); + ss_dassert(home_dir != NULL); rc = MAXSCALE_HOMELESS; goto return_main; } sprintf(mysql_home, "%s/mysql", home_dir); setenv("MYSQL_HOME", mysql_home, 1); } + else + { + char* log_context = strdup("Home directory command-line argument"); + char* errstr; + + errstr = check_dir_access(home_dir); + + if (errstr != NULL) + { + char* logstr = (char*)malloc(strlen(log_context)+ + 1+ + strlen(errstr)+ + 1); + + snprintf(logstr, + strlen(log_context)+ + 1+ + strlen(errstr)+1, + "%s: %s", + log_context, + errstr); + + print_log_n_stderr(true, true, logstr, logstr, 0); + + free(errstr); + free(logstr); + rc = MAXSCALE_HOMELESS; + goto return_main; + } + else if (!daemon_mode) + { + fprintf(stderr, + "Using %s as MAXSCALE_HOME = %s\n", + log_context, + home_dir); + } + free(log_context); + } /*< * Init Log Manager for MaxScale. @@ -1386,8 +1456,9 @@ int main(int argc, char **argv) * argv[0] */ { - char buf[1024]; - char *argv[8]; + char buf[1024]; + char *argv[8]; + bool succp; sprintf(buf, "%s/log", home_dir); mkdir(buf, 0777); @@ -1400,7 +1471,7 @@ int main(int argc, char **argv) argv[4] = "LOGFILE_MESSAGE,LOGFILE_ERROR" "LOGFILE_DEBUG,LOGFILE_TRACE"; argv[5] = NULL; - skygw_logmanager_init(5, argv); + succp = skygw_logmanager_init(5, argv); } else { @@ -1409,7 +1480,13 @@ int main(int argc, char **argv) argv[5] = "-l"; /*< write to syslog */ argv[6] = "LOGFILE_MESSAGE,LOGFILE_ERROR"; /*< ..these logs to syslog */ argv[7] = NULL; - skygw_logmanager_init(7, argv); + succp = skygw_logmanager_init(7, argv); + } + + if (!succp) + { + rc = MAXSCALE_BADCONFIG; + goto return_main; } } @@ -1670,9 +1747,11 @@ static void log_flush_cb( void* arg) { ssize_t timeout_ms = *(ssize_t *)arg; - const struct timespec ts1 = {0, 1000000*timeout_ms}; - struct timespec ts2; + struct timespec ts1; + ts1.tv_sec = timeout_ms/1000; + ts1.tv_nsec = (timeout_ms%1000)*1000000; + LOGIF(LM, (skygw_log_write(LOGFILE_MESSAGE, "Started MaxScale log flusher."))); while (!do_exit) { @@ -1680,7 +1759,7 @@ static void log_flush_cb( skygw_log_flush(LOGFILE_MESSAGE); skygw_log_flush(LOGFILE_TRACE); skygw_log_flush(LOGFILE_DEBUG); - nanosleep(&ts1, &ts2); + nanosleep(&ts1, NULL); } LOGIF(LM, (skygw_log_write(LOGFILE_MESSAGE, "Finished MaxScale log flusher."))); diff --git a/server/core/hint.c b/server/core/hint.c index 052c02486..0564625a4 100644 --- a/server/core/hint.c +++ b/server/core/hint.c @@ -116,7 +116,7 @@ HINT *hint; return head; hint->next = head; hint->type = HINT_PARAMETER; - hint->data = pname; + hint->data = strdup(pname); hint->value = strdup(value); return hint; } @@ -151,4 +151,4 @@ bool hint_exists( p_hint = &(*p_hint)->next; } return succp; -} \ No newline at end of file +} diff --git a/server/core/poll.c b/server/core/poll.c index e1a3f80ec..bfb1e65c6 100644 --- a/server/core/poll.c +++ b/server/core/poll.c @@ -15,6 +15,7 @@ * * Copyright MariaDB Corporation Ab 2013-2014 */ +#include #include #include #include diff --git a/server/core/test/CMakeLists.txt b/server/core/test/CMakeLists.txt index 14a80cd36..ea2cb4a95 100644 --- a/server/core/test/CMakeLists.txt +++ b/server/core/test/CMakeLists.txt @@ -1,3 +1,4 @@ +add_executable(test_mysql_users test_mysql_users.c) add_executable(test_hash testhash.c) add_executable(test_hint testhint.c) add_executable(test_spinlock testspinlock.c) @@ -10,6 +11,7 @@ add_executable(test_service testservice.c) add_executable(test_server testserver.c) add_executable(test_users testusers.c) add_executable(test_adminusers testadminusers.c) +target_link_libraries(test_mysql_users fullcore MySQLClient) target_link_libraries(test_hash fullcore) target_link_libraries(test_hint fullcore) target_link_libraries(test_spinlock fullcore) @@ -22,6 +24,7 @@ target_link_libraries(test_service fullcore) target_link_libraries(test_server fullcore) target_link_libraries(test_users fullcore) target_link_libraries(test_adminusers fullcore) +add_test(testMySQLUsers test_mysql_users) add_test(TestHash test_hash) add_test(TestHint test_hint) add_test(TestSpinlock test_spinlock) diff --git a/server/core/test/makefile.mysql_users b/server/core/test/makefile.mysql_users deleted file mode 100644 index 074188555..000000000 --- a/server/core/test/makefile.mysql_users +++ /dev/null @@ -1,32 +0,0 @@ -# cleantests - clean local and subdirectories' tests -# buildtests - build all local and subdirectories' tests -# runtests - run all local tests -# testall - clean, build and run local and subdirectories' tests - -include ../../../build_gateway.inc -include ../../../makefile.inc - -CC=cc -DEBUG=Y -cleantests: - - $(DEL) *.o - - $(DEL) test_mysql_users - - $(DEL) *~ - -testall: cleantests buildtests runtests - -buildtests : - $(CC) $(CFLAGS) \ - -I$(ROOT_PATH)/server/include \ - -I$(ROOT_PATH)/utils \ - -I$(ROOT_PATH)/log_manager \ - test_mysql_users.c ../secrets.o ../service.o ../gwbitmask.o ../load_utils.o ../session.o ../poll.o ../dcb.o ../utils.o ../buffer.o ../gw_utils.o ../hashtable.o ../atomic.o ../spinlock.o ../users.o ../dbusers.o ../../../utils/skygw_utils.o ../../../log_manager/log_manager.o -o test_mysql_users -L$(EMBEDDED_LIB) -lmysqlclient -lpthread -lssl -lz -lm -lcrypt -lcrypto -ldl -laio -lrt -lstdc++ -runtests: - @echo "" - @echo "-------------------------------" - @echo $(shell date) - @echo "Test MaxScale core" - @echo "-------------------------------" - @echo "" - @echo "MaxSclale Load MySQL users" - @./test_mysql_users diff --git a/server/core/test/test_mysql_users.c b/server/core/test/test_mysql_users.c index 7dc789d83..1d0193c45 100644 --- a/server/core/test/test_mysql_users.c +++ b/server/core/test/test_mysql_users.c @@ -24,6 +24,7 @@ * Date Who Description * 14/02/2014 Massimiliano Pinto Initial implementation * 17/02/2014 Massimiliano Pinto Added check ipv4 + * 03/10/2014 Massimiliano Pinto Added check for wildcard hosts * * @endverbatim */ @@ -77,6 +78,7 @@ int set_and_get_single_mysql_users_ipv4(char *username, unsigned long ipv4, char /* add user@host as key and passwd as value in the MySQL users hash table */ if (!mysql_users_add(mysql_users, &key, password)) { fprintf(stderr, "Failed adding %s@%s(%lu)\n", username, ret_ip, fix_ipv4); + users_free(mysql_users); return 1; } @@ -107,6 +109,7 @@ int set_and_get_single_mysql_users(char *username, char *hostname, char *passwor char *fetch_data; mysql_users = mysql_users_alloc(); + /* prepare the user@host data struct */ memset(&serv_addr, 0, sizeof(serv_addr)); memset(&key, 0, sizeof(key)); @@ -115,6 +118,7 @@ int set_and_get_single_mysql_users(char *username, char *hostname, char *passwor if (hostname) if(!setipaddress(&serv_addr.sin_addr, hostname)) { fprintf(stderr, "setipaddress failed for host [%s]\n", hostname); + users_free(mysql_users); return 1; } if (username) @@ -129,6 +133,7 @@ int set_and_get_single_mysql_users(char *username, char *hostname, char *passwor /* add user@host as key and passwd as value in the MySQL users hash table */ if (!mysql_users_add(mysql_users, &key, password)) { fprintf(stderr, "mysql_users_add() failed for %s@%s\n", username, hostname); + users_free(mysql_users); return 1; } @@ -138,6 +143,7 @@ int set_and_get_single_mysql_users(char *username, char *hostname, char *passwor if (hostname) if(!setipaddress(&serv_addr.sin_addr, hostname)) { fprintf(stderr, "setipaddress failed for host [%s]\n", hostname); + users_free(mysql_users); return 1; } key.user = username; @@ -153,6 +159,73 @@ int set_and_get_single_mysql_users(char *username, char *hostname, char *passwor return 0; } +int set_and_get_mysql_users_wildcards(char *username, char *hostname, char *password, char *from) { + USERS *mysql_users; + int ret; + struct sockaddr_in client_addr; + DCB *dcb; + SERVICE *service; + + dcb = dcb_alloc(DCB_ROLE_INTERNAL); + + if (dcb == NULL) { + fprintf(stderr, "dcb_alloc() failed\n"); + return 1; + } + if ((service = (SERVICE *)calloc(1, sizeof(SERVICE))) == NULL) { + fprintf(stderr, "service_alloc() failed\n"); + dcb_free(dcb); + return 1; + } + + memset(&client_addr, 0, sizeof(client_addr)); + + if (hostname) { + if(!setipaddress(&client_addr.sin_addr, from)) { + fprintf(stderr, "setipaddress failed for host [%s]\n", from); + free(service); + dcb_free(dcb); + return 1; + } + } + + /* client IPv4 in raw data*/ + memcpy(&dcb->ipv4, (struct sockaddr_in *)&client_addr, sizeof(struct sockaddr_in)); + + dcb->service = service; + + mysql_users = mysql_users_alloc(); + + service->users = mysql_users; + + + // the routine returns 1 on success + ret = add_mysql_users_with_host_ipv4(mysql_users, username, hostname, password); + if (!ret) { + fprintf(stderr, "add_mysql_users_with_host_ipv4 passed(%s@%s, %s) FAILED\n", username, hostname, password); + users_free(mysql_users); + free(service); + dcb_free(dcb); + + return 1; + } else { + char db_passwd[100]=""; + + dcb->remote=strdup(from); + //fprintf(stderr, "add_mysql_users_with_host_ipv4 passed(%s@%s, %s) OK\n", username, hostname, password); + + fprintf(stderr, "Checking '%s' @ '%s' against (%s@%s)\n", username, from, username, hostname); + + // returns 0 on success + ret = gw_find_mysql_user_password_sha1(username, db_passwd, dcb); + } + + users_free(mysql_users); + free(service); + dcb_free(dcb); + + return ret; +} int main() { int ret; @@ -180,6 +253,7 @@ int main() { assert(ret == 1); ret = set_and_get_single_mysql_users(NULL, NULL, NULL); assert(ret == 1); + ret = set_and_get_single_mysql_users_ipv4("negative", -467295, "_ncd"); assert(ret == 1); ret = set_and_get_single_mysql_users_ipv4("extra", 0xFFFFFFFFFUL * 100, "JJcd"); @@ -189,19 +263,77 @@ int main() { ret = set_and_get_single_mysql_users_ipv4(NULL, '\0', "JJcd"); assert(ret == 1); + for (i = 256*256*256; i <= 256*256*256 + 5; i++) { char user[129] = ""; snprintf(user, 128, "user_%i", k); ret = set_and_get_single_mysql_users_ipv4(user, i, "JJcd"); + assert(ret == 0); k++; } + ret = set_and_get_mysql_users_wildcards("pippo", "%", "one", "127.0.0.1"); + if (ret) fprintf(stderr, "\t-- Expecting no match\n"); + assert(ret == 1); + + ret = set_and_get_mysql_users_wildcards("pippo", "%", "", "127.0.0.1"); + if (ret) fprintf(stderr, "\t-- Expecting no match\n"); + assert(ret == 1); + + ret = set_and_get_mysql_users_wildcards("pippo", "%", "two", "192.168.2.2"); + if (!ret) fprintf(stderr, "\t-- Expecting ok\n"); + assert(ret == 0); + + ret = set_and_get_mysql_users_wildcards("pippo", "192.168.1.%", "foo", "192.168.2.2"); + if (ret) fprintf(stderr, "\t-- Expecting no match\n"); + assert(ret == 1); + + ret = set_and_get_mysql_users_wildcards("pippo", "192.168.%.%", "foo", "192.168.2.2"); + if (!ret) fprintf(stderr, "\t-- Expecting ok\n"); + assert(ret == 0); + + ret = set_and_get_mysql_users_wildcards("pippo", "192.%.%.%", "foo", "192.68.0.2"); + if (!ret) fprintf(stderr, "\t-- Expecting ok\n"); + assert(ret == 0); + + ret = set_and_get_mysql_users_wildcards("pippo", "192.%.%.%", "foo", "192.0.0.2"); + if (!ret) fprintf(stderr, "\t-- Expecting ok\n"); + assert(ret == 0); + + ret = set_and_get_mysql_users_wildcards("pippo", "192.0.%.%", "foo", "192.2.0.2"); + if (ret) fprintf(stderr, "\t-- Expecting no match\n"); + assert(ret == 1); + + ret = set_and_get_mysql_users_wildcards("pippo", "192.0.0.1", "foo", "192.0.0.2"); + if (ret) fprintf(stderr, "\t-- Expecting no match\n"); + assert(ret == 1); + + ret = set_and_get_mysql_users_wildcards("pippo", "192.0.%.%", "foo", "192.1.0.2"); + if (ret) fprintf(stderr, "\t-- Expecting no match\n"); + assert(ret == 1); + + ret = set_and_get_mysql_users_wildcards("pippo", "192.0.0.%", "y78764o", "192.3.2.1"); + if (ret) fprintf(stderr, "\t-- Expecting no match\n"); + assert(ret == 1); + + ret = set_and_get_mysql_users_wildcards("pippo", "192.0.%.%", "1234567890123456789012345678901234567890", "192.3.2.1"); + if (ret) fprintf(stderr, "\t-- Expecting no match\n"); + assert(ret == 1); + + ret = set_and_get_mysql_users_wildcards("pippo", "192.%.%.%", "1234567890123456789012345678901234567890f8__uuo5", "192.3.2.1"); + if (!ret) fprintf(stderr, "\t-- Expecting ok\n"); + assert(ret == 0); + + ret = set_and_get_mysql_users_wildcards("pippo", "192.0.0.%", "fo887778o", "192.134.0.2"); + if (ret) fprintf(stderr, "\t-- Expecting no match\n"); + assert(ret == 1); + fprintf(stderr, "----------------\n"); fprintf(stderr, "<<< Test completed\n"); time(&t); fprintf(stderr, "%s\n", asctime(localtime(&t))); - return ret; + return 0; } diff --git a/server/core/test/testadminusers.c b/server/core/test/testadminusers.c index 4a67b1f5b..eb2ee8e40 100644 --- a/server/core/test/testadminusers.c +++ b/server/core/test/testadminusers.c @@ -266,6 +266,14 @@ int main(int argc, char **argv) { int result = 0; +char *home, buf[1024]; + + /* Unlink any existing password file before running this test */ + if ((home = getenv("MAXSCALE_HOME")) == NULL) + home = "/usr/local/skysql"; + sprintf(buf, "%s/etc/passwd", home); + if (strcmp(buf, "/etc/passwd") != 0) + unlink(buf); result += test1(); result += test2(); diff --git a/server/core/test/testbuffer.c b/server/core/test/testbuffer.c index 87ebf858b..ee8507161 100644 --- a/server/core/test/testbuffer.c +++ b/server/core/test/testbuffer.c @@ -13,7 +13,7 @@ * this program; if not, write to the Free Software Foundation, Inc., 51 * Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * - * Copyright SkySQL Ab 2014 + * Copyright MariaDB Corporation Ab 2014 */ /** @@ -32,6 +32,7 @@ #include #include +#include /** * test1 Allocate a buffer and do lots of things @@ -41,6 +42,7 @@ static int test1() { GWBUF *buffer, *extra, *clone, *partclone, *transform; +HINT *hint; int size = 100; int bite1 = 35; int bite2 = 60; @@ -58,6 +60,10 @@ int buflen; ss_info_dassert(size == buflen, "Incorrect buffer size"); ss_info_dassert(0 == GWBUF_EMPTY(buffer), "Buffer should not be empty"); ss_info_dassert(GWBUF_IS_TYPE_UNDEFINED(buffer), "Buffer type should be undefined"); + ss_dfprintf(stderr, "\t..done\nSet a hint for the buffer"); + hint = hint_create_parameter(NULL, strdup("name"), "value"); + gwbuf_add_hint(buffer, hint); + ss_info_dassert(hint == buffer->hint, "Buffer should point to first and only hint"); ss_dfprintf(stderr, "\t..done\nSet a property for the buffer"); gwbuf_add_property(buffer, "name", "value"); ss_info_dassert(0 == strcmp("value", gwbuf_get_property(buffer, "name")), "Should now have correct property"); diff --git a/server/core/test/testdcb.c b/server/core/test/testdcb.c index 5f8e18601..2703763f0 100644 --- a/server/core/test/testdcb.c +++ b/server/core/test/testdcb.c @@ -13,7 +13,7 @@ * this program; if not, write to the Free Software Foundation, Inc., 51 * Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * - * Copyright SkySQL Ab 2014 + * Copyright MariaDB Corporation Ab 2014 */ /** @@ -51,6 +51,7 @@ int buflen; ss_dfprintf(stderr, "testdcb : creating buffer with type DCB_ROLE_SERVICE_LISTENER"); dcb = dcb_alloc(DCB_ROLE_SERVICE_LISTENER); + printDCB(dcb); ss_info_dassert(dcb_isvalid(dcb), "New DCB must be valid"); ss_dfprintf(stderr, "\t..done\nAllocated dcb."); clone = dcb_clone(dcb); diff --git a/server/core/test/testgwbitmask.c b/server/core/test/testgwbitmask.c new file mode 100644 index 000000000..86bad1245 --- /dev/null +++ b/server/core/test/testgwbitmask.c @@ -0,0 +1,83 @@ +/* + * This file is distributed as part of MaxScale. It 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. + * + * 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 2014 + */ + +/** + * + * @verbatim + * Revision History + * + * Date Who Description + * 13-10-2014 Martin Brampton Initial implementation + * + * @endverbatim + */ + +#include +#include +#include + +#include + +#include + +/** + * test1 Allocate table of users and mess around with it + * + */ + +static int +test1() +{ +static GWBITMASK bitmask, another; +int i; + + /* Hint tests */ + ss_dfprintf(stderr, + "testgwbitmask : Initialise a bitmask"); + bitmask_init(&bitmask); + ss_info_dassert(BIT_LENGTH_INITIAL == bitmask.length, "Length should be initial length."); + for (i = 0; i < BIT_LENGTH_INITIAL; i++) { + ss_info_dassert(0 == bitmask_isset(&bitmask, i), "All bits should initially be zero"); + } + ss_info_dassert(0 != bitmask_isallclear(&bitmask), "Should be all clear"); + ss_dfprintf(stderr, "\t..done\nSet an arbitrary bit."); + bitmask_set(&bitmask, 17); + bitmask_copy(&another, &bitmask); + ss_info_dassert(0 != bitmask_isset(&another, 17), "Test bit should be set"); + ss_dfprintf(stderr, "\t..done\nClear the arbitrary bit."); + bitmask_clear(&bitmask, 17); + ss_info_dassert(0 == bitmask_isset(&bitmask, 17), "Test bit should be clear"); + ss_info_dassert(0 != bitmask_isallclear(&bitmask), "Should be all clear"); + ss_dfprintf(stderr, "\t..done\nFree the bitmask."); + bitmask_free(&bitmask); + ss_info_dassert(0 == bitmask.length, "Length should be zero after bit mask freed."); + ss_dfprintf(stderr, "\t..done\n"); + + return 0; + +} + +int main(int argc, char **argv) +{ +int result = 0; + + result += test1(); + + exit(result); +} + diff --git a/server/core/test/testhint.c b/server/core/test/testhint.c index 3d2241642..3ec5d9953 100644 --- a/server/core/test/testhint.c +++ b/server/core/test/testhint.c @@ -13,7 +13,7 @@ * this program; if not, write to the Free Software Foundation, Inc., 51 * Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * - * Copyright SkySQL Ab 2014 + * Copyright MariaDB Corporation Ab 2014 */ /** @@ -49,7 +49,7 @@ HINT *hint; hint = hint_create_parameter(NULL, strdup("name"), "value"); ss_info_dassert(NULL != hint, "New hint list should not be null"); ss_info_dassert(0 == strcmp("value", hint->value), "Hint value should be correct"); - ss_info_dassert(0 != hint_exists(hint, HINT_PARAMETER), "Hint of parameter type should exist"); + ss_info_dassert(0 != hint_exists(&hint, HINT_PARAMETER), "Hint of parameter type should exist"); ss_dfprintf(stderr, "\t..done\nFree hints."); if (NULL != hint) hint_free(hint); ss_dfprintf(stderr, "\t..done\n"); diff --git a/server/core/test/testmodutil.c b/server/core/test/testmodutil.c index e83facdc5..b37203ff4 100644 --- a/server/core/test/testmodutil.c +++ b/server/core/test/testmodutil.c @@ -13,7 +13,7 @@ * this program; if not, write to the Free Software Foundation, Inc., 51 * Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * - * Copyright SkySQL Ab 2014 + * Copyright MariaDB Corporation Ab 2014 */ /** diff --git a/server/core/test/testpoll.c b/server/core/test/testpoll.c index aee799bb4..4d8d4cc04 100644 --- a/server/core/test/testpoll.c +++ b/server/core/test/testpoll.c @@ -13,7 +13,7 @@ * this program; if not, write to the Free Software Foundation, Inc., 51 * Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * - * Copyright SkySQL Ab 2014 + * Copyright MariaDB Corporation Ab 2014 */ /** diff --git a/server/core/test/testserver.c b/server/core/test/testserver.c index 56a69e65d..3b05188ab 100644 --- a/server/core/test/testserver.c +++ b/server/core/test/testserver.c @@ -13,7 +13,7 @@ * this program; if not, write to the Free Software Foundation, Inc., 51 * Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * - * Copyright SkySQL Ab 2014 + * Copyright MariaDB Corporation Ab 2014 */ /** diff --git a/server/core/test/testservice.c b/server/core/test/testservice.c index 2b12c8062..579bd617f 100644 --- a/server/core/test/testservice.c +++ b/server/core/test/testservice.c @@ -13,7 +13,7 @@ * this program; if not, write to the Free Software Foundation, Inc., 51 * Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * - * Copyright SkySQL Ab 2014 + * Copyright MariaDB Corporation Ab 2014 */ /** diff --git a/server/core/test/testusers.c b/server/core/test/testusers.c index f407b273a..3f13cad9b 100644 --- a/server/core/test/testusers.c +++ b/server/core/test/testusers.c @@ -13,7 +13,7 @@ * this program; if not, write to the Free Software Foundation, Inc., 51 * Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * - * Copyright SkySQL Ab 2014 + * Copyright MariaDB Corporation Ab 2014 */ /** diff --git a/server/include/dbusers.h b/server/include/dbusers.h index f9f4a50ab..bcaff05ad 100644 --- a/server/include/dbusers.h +++ b/server/include/dbusers.h @@ -32,6 +32,7 @@ * 25/06/13 Mark Riddoch Initial implementation * 25/02/13 Massimiliano Pinto Added users table refresh rate default values * 28/02/14 Massimiliano Pinto Added MySQL user and host data structure + * 03/10/14 Massimiliano Pinto Added netmask to MySQL user and host data structure * * @endverbatim */ @@ -52,11 +53,13 @@ typedef struct mysql_user_host_key { char *user; struct sockaddr_in ipv4; + int netmask; } MYSQL_USER_HOST; extern int load_mysql_users(SERVICE *service); extern int reload_mysql_users(SERVICE *service); extern int mysql_users_add(USERS *users, MYSQL_USER_HOST *key, char *auth); +extern int add_mysql_users_with_host_ipv4(USERS *users, char *user, char *host, char *passwd); extern USERS *mysql_users_alloc(); extern char *mysql_users_fetch(USERS *users, MYSQL_USER_HOST *key); extern int replace_mysql_users(SERVICE *service); diff --git a/server/modules/filter/mqfilter.c b/server/modules/filter/mqfilter.c index e6a6c12b1..ed0096bbf 100644 --- a/server/modules/filter/mqfilter.c +++ b/server/modules/filter/mqfilter.c @@ -58,6 +58,7 @@ *@endverbatim * See the individual struct documentations for logging trigger parameters */ +#include #include #include #include diff --git a/server/modules/filter/test/Makefile b/server/modules/filter/test/Makefile old mode 100755 new mode 100644 index 5eb6561f7..12546291d --- a/server/modules/filter/test/Makefile +++ b/server/modules/filter/test/Makefile @@ -1,4 +1,4 @@ -# This file is distributed as part of MaxScale form SkySQL. It is free +# This file is distributed as part of MaxScale form MariaDB Corporation. It 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. @@ -12,7 +12,7 @@ # this program; if not, write to the Free Software Foundation, Inc., 51 # Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. # -# Copyright SkySQL Ab 2014 +# Copyright MariaDB Corporation Ab 2014 include ../../../../build_gateway.inc diff --git a/server/modules/filter/test/harness.h b/server/modules/filter/test/harness.h index 69b12b9d9..c30c266c2 100644 --- a/server/modules/filter/test/harness.h +++ b/server/modules/filter/test/harness.h @@ -1,7 +1,7 @@ #ifndef _FILTER_HARNESS_H #define _FILTER_HARNESS_H /* - * This file is distributed as part of the SkySQL Gateway. It is free + * This file is distributed as part of the MariaDB Corporation MaxScale. It 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. @@ -15,7 +15,7 @@ * this program; if not, write to the Free Software Foundation, Inc., 51 * Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * - * Copyright SkySQL Ab 2013 + * Copyright MariaDB Corporation Ab 2014 */ /** diff --git a/server/modules/protocol/mysql_client.c b/server/modules/protocol/mysql_client.c index 06f83f3e1..92317cb40 100644 --- a/server/modules/protocol/mysql_client.c +++ b/server/modules/protocol/mysql_client.c @@ -558,6 +558,7 @@ static char* create_auth_fail_str( { sprintf(errstr, ferrstr, uname, hostaddr, (*sha1 == '\0' ? "NO" : "YES")); } + free(uname); retblock: return errstr; diff --git a/server/modules/protocol/mysql_common.c b/server/modules/protocol/mysql_common.c index 684829fdf..c098263c2 100644 --- a/server/modules/protocol/mysql_common.c +++ b/server/modules/protocol/mysql_common.c @@ -31,6 +31,9 @@ * localhost entry should be added for the selected user in the backends. * Setting to 1 allow localhost (127.0.0.1 or socket) to match the any host grant via * user@% + * 29/09/2014 Massimiliano Pinto Added Mysql user@host authentication with wildcard in IPv4 hosts: + * x.y.z.%, x.y.%.%, x.%.%.% + * 03/10/2014 Massimiliano Pinto Added netmask for wildcard in IPv4 hosts. * */ @@ -1310,7 +1313,7 @@ int gw_check_mysql_scramble_data(DCB *dcb, uint8_t *token, unsigned int token_le /** * gw_find_mysql_user_password_sha1 * - * The routine fetches look for an user int he MaxScale users' table + * The routine fetches look for an user int the MaxScale users' table * The users' table is dcb->service->users or a different one specified with void *repository * * If found the HEX password, representing sha1(sha1(password)), is converted in binary data and @@ -1334,6 +1337,7 @@ int gw_find_mysql_user_password_sha1(char *username, uint8_t *gateway_password, key.user = username; memcpy(&key.ipv4, client, sizeof(struct sockaddr_in)); + key.netmask = 32; LOGIF(LD, (skygw_log_write_flush( @@ -1343,73 +1347,119 @@ int gw_find_mysql_user_password_sha1(char *username, uint8_t *gateway_password, key.user, dcb->remote))); - /* look for user@current_host now */ + /* look for user@current_ipv4 now */ user_password = mysql_users_fetch(service->users, &key); if (!user_password) { - /* The user is not authenticated @ current host */ + /* The user is not authenticated @ current IPv4 */ - /* 1) Check for localhost first. - * The check for localhost is 127.0.0.1 (IPv4 only) - */ - - if ((key.ipv4.sin_addr.s_addr == 0x0100007F) && !dcb->service->localhost_match_wildcard_host) { - /* Skip the wildcard check and return 1 */ - LOGIF(LE, - (skygw_log_write_flush( - LOGFILE_ERROR, - "Error : user %s@%s not found, try set " - "'localhost_match_wildcard_host=1' in " - "service definition of the configuration " - "file.", - key.user, - dcb->remote))); - - return 1; - } - - /* 2) Continue and check for wildcard host, user@% - * Return 1 if no match - */ - - memset(&key.ipv4, 0, sizeof(struct sockaddr_in)); - - LOGIF(LD, - (skygw_log_write_flush( - LOGFILE_DEBUG, - "%lu [MySQL Client Auth], checking user [%s@%s] with wildcard host [%%]", - pthread_self(), - key.user, - dcb->remote))); - - user_password = mysql_users_fetch(service->users, &key); - - if (!user_password) { - /* the user@% was not found. - * Return 1 + while (1) { + /* + * (1) Check for localhost first: 127.0.0.1 (IPv4 only) */ + + if ((key.ipv4.sin_addr.s_addr == 0x0100007F) && !dcb->service->localhost_match_wildcard_host) { + /* Skip the wildcard check and return 1 */ + LOGIF(LE, + (skygw_log_write_flush( + LOGFILE_ERROR, + "Error : user %s@%s not found, try set " + "'localhost_match_wildcard_host=1' in " + "service definition of the configuration " + "file.", + key.user, + dcb->remote))); + + break; + } + + /* + * (2) check for possible IPv4 class C,B,A networks + */ + + /* Class C check */ + key.ipv4.sin_addr.s_addr &= 0x00FFFFFF; + key.netmask -= 8; + + user_password = mysql_users_fetch(service->users, &key); + + if (user_password) { + break; + } + + /* Class B check */ + key.ipv4.sin_addr.s_addr &= 0x0000FFFF; + key.netmask -= 8; + + user_password = mysql_users_fetch(service->users, &key); + + if (user_password) { + break; + } + + /* Class A check */ + key.ipv4.sin_addr.s_addr &= 0x000000FF; + key.netmask -= 8; + + user_password = mysql_users_fetch(service->users, &key); + + if (user_password) { + break; + } + + /* + * (3) Continue check for wildcard host, user@% + */ + + memset(&key.ipv4, 0, sizeof(struct sockaddr_in)); + key.netmask = 0; + LOGIF(LD, (skygw_log_write_flush( LOGFILE_DEBUG, - "%lu [MySQL Client Auth], user [%s@%s] not existent", + "%lu [MySQL Client Auth], checking user [%s@%s] with wildcard host [%%]", pthread_self(), key.user, dcb->remote))); - return 1; + + user_password = mysql_users_fetch(service->users, &key); + + if (!user_password) { + /* + * the user@% has not been found. + */ + + LOGIF(LD, + (skygw_log_write_flush( + LOGFILE_DEBUG, + "%lu [MySQL Client Auth], user [%s@%s] not existent", + pthread_self(), + key.user, + dcb->remote))); + break; + } + + break; } } - /* user@host found: now check the password - * - * Convert the hex data (40 bytes) to binary (20 bytes). - * The gateway_password represents the SHA1(SHA1(real_password)). - * Please note: the real_password is unknown and SHA1(real_password) is unknown as well - */ + /* If user@host has been found we get the the password in binary format*/ + if (user_password) { + /* + * Convert the hex data (40 bytes) to binary (20 bytes). + * The gateway_password represents the SHA1(SHA1(real_password)). + * Please note: the real_password is unknown and SHA1(real_password) is unknown as well + */ + int passwd_len=strlen(user_password); + if (passwd_len) { + passwd_len = (passwd_len <= (SHA_DIGEST_LENGTH * 2)) ? passwd_len : (SHA_DIGEST_LENGTH * 2); + gw_hex2bin(gateway_password, user_password, passwd_len); + } - if (strlen(user_password)) - gw_hex2bin(gateway_password, user_password, SHA_DIGEST_LENGTH * 2); - - return 0; + return 0; + } else { + return 1; + } } /** @@ -1652,11 +1702,9 @@ void protocol_archive_srv_command( s1 = &p->protocol_command; - LOGIF(LD, (skygw_log_write( - LOGFILE_DEBUG, - "%lu [protocol_archive_srv_command] Move command %s from fd %d " - "to command history.", - pthread_self(), + LOGIF(LT, (skygw_log_write( + LOGFILE_TRACE, + "Move command %s from fd %d to command history.", STRPACKETTYPE(s1->scom_cmd), p->owner_dcb->fd))); @@ -1728,8 +1776,8 @@ void protocol_add_srv_command( p->protocol_command.scom_next = server_command_init(NULL, cmd); } - LOGIF(LD, (skygw_log_write( - LOGFILE_DEBUG, + LOGIF(LT, (skygw_log_write( + LOGFILE_TRACE, "Added command %s to fd %d.", STRPACKETTYPE(cmd), p->owner_dcb->fd))); @@ -1739,8 +1787,8 @@ void protocol_add_srv_command( while (c != NULL && c->scom_cmd != MYSQL_COM_UNDEFINED) { - LOGIF(LD, (skygw_log_write( - LOGFILE_DEBUG, + LOGIF(LT, (skygw_log_write( + LOGFILE_TRACE, "fd %d : %d %s", p->owner_dcb->fd, c->scom_cmd, diff --git a/server/modules/routing/debugcmd.c b/server/modules/routing/debugcmd.c index 8f51d531a..65384bfc6 100644 --- a/server/modules/routing/debugcmd.c +++ b/server/modules/routing/debugcmd.c @@ -44,6 +44,7 @@ * * @endverbatim */ +#include #include #include #include diff --git a/server/modules/routing/readwritesplit/readwritesplit.c b/server/modules/routing/readwritesplit/readwritesplit.c index 8d5f51727..07820b076 100644 --- a/server/modules/routing/readwritesplit/readwritesplit.c +++ b/server/modules/routing/readwritesplit/readwritesplit.c @@ -15,6 +15,7 @@ * * Copyright MariaDB Corporation Ab 2013-2014 */ +#include #include #include #include @@ -1707,6 +1708,12 @@ static int routeQuery( } goto retblock; } + /** If buffer is not contiguous, make it such */ + if (querybuf->next != NULL) + { + querybuf = gwbuf_make_contiguous(querybuf); + } + master_dcb = router_cli_ses->rses_master_ref->bref_dcb; CHK_DCB(master_dcb); diff --git a/server/modules/routing/readwritesplit/test/rwsplit.sh b/server/modules/routing/readwritesplit/test/rwsplit.sh index fcca4ac37..7c9ec5edb 100755 --- a/server/modules/routing/readwritesplit/test/rwsplit.sh +++ b/server/modules/routing/readwritesplit/test/rwsplit.sh @@ -18,7 +18,7 @@ echo "" exit 1 fi -if [ "$#" == "$NARGS" ] +if [ "$#" = "$NARGS" ] then echo "CTest mode" TDIR=$7 #this is only used by CMake @@ -267,7 +267,7 @@ do break fi done -if [[ "$err" == "" ]] +if [[ "$err" = "" ]] then echo "TEST PASSED" >> $TLOG else @@ -293,7 +293,7 @@ do break fi done -if [[ "$err" == "" ]] +if [[ "$err" = "" ]] then echo "TEST PASSED" >> $TLOG else diff --git a/server/test/CMakeLists.txt b/server/test/CMakeLists.txt deleted file mode 100644 index 47eb22199..000000000 --- a/server/test/CMakeLists.txt +++ /dev/null @@ -1,3 +0,0 @@ -if(BUILD_TESTS) - install(FILES MaxScale_test.cnf DESTINATION etc RENAME MaxScale.cnf) -endif() diff --git a/support/changelog.md b/support/changelog.md new file mode 100644 index 000000000..d9917d9b7 --- /dev/null +++ b/support/changelog.md @@ -0,0 +1,2 @@ +### 2013/06/15 ++ Some example changes diff --git a/support/faq.md b/support/faq.md new file mode 100644 index 000000000..dcb005de6 --- /dev/null +++ b/support/faq.md @@ -0,0 +1,2 @@ +### is this a question? +An answer diff --git a/support/gitdoc.json b/support/gitdoc.json new file mode 100644 index 000000000..d1d45cd9c --- /dev/null +++ b/support/gitdoc.json @@ -0,0 +1,5 @@ +{ + "googleGroup": "group_name", + "irc": {"server": "irc.freenode.net", "channel": "#a_channel"}, + "domain": "yoursite.com" +} diff --git a/support/guide/overview.md b/support/guide/overview.md new file mode 100644 index 000000000..2d943c295 --- /dev/null +++ b/support/guide/overview.md @@ -0,0 +1,2 @@ +This directory is useful for many things, like how to install your software, if it has a CLI you +can tell people how to use it, any many other uses. diff --git a/support/reference/layout.md b/support/reference/layout.md new file mode 100644 index 000000000..622a999bc --- /dev/null +++ b/support/reference/layout.md @@ -0,0 +1,14 @@ +### Navigation +On the documentation/guide/reference pages, the sections created in your reference and guide +directories will be listed on the right as the main navigation links, you can have subsections too. +Any h3(###) lines you include in your reference/guide files will be added to the subsections under +the main section link. They will be hidden until you hover over the main section link or have +clicked the section link. + +### Headers +You can use any size headers you want, but it is adivised to use h3(###) and smaller, anything +bigger than h3(e.g. h2) is usually too big for the default layout. + +### Scrolling +When you scroll down the page the navigation will follow you if the screen is big enough for the +navigation to fit on the right side, otherwise it sits at the top. diff --git a/support/reference/premium.md b/support/reference/premium.md new file mode 100644 index 000000000..25500d5a6 --- /dev/null +++ b/support/reference/premium.md @@ -0,0 +1,27 @@ +### Premium repositories +Once you get premium, the plan you selected delegates the number of premium repositories you're +allowed to have. Premium repositories have many features not available without a premium plan. + +### Personally hosted repositories +The premium repositories you select are allowed to be hosted on their own domains, you can choose +a domain in your `support/gitdoc.json` file. Just add a `domain` field with your domain, and +point your domain at our site, and it will automatically load your repo. + +### Private repositories +Private repositories cannot be viewed without being set as a premium repository. + +### Custom CSS +You're premium repos can have custom layouts through CSS. Once you add a premium repo, simply create +the file `support/styles.css` and refresh your repo, when the page refreshes you'll be able to +see the custom CSS in action. + +### Branches +On premium repositories, you can select the branch you want to pull updates from, this is useful +if you plan to display the documentation for a specific version of your software. + +### Standard Git repos +Standard Git repositories from non Github servers are supported after you have a premium plan. +To add a standard repo to your account, add support for the repository(You can get the setup +details from your profile page.), after that go to your profile page and at the bottom will be +a form where you can fill out the information to add your repository. After that it can be updated +just like any other repository. diff --git a/support/tutorial.md b/support/tutorial.md new file mode 100644 index 000000000..f27a6b372 --- /dev/null +++ b/support/tutorial.md @@ -0,0 +1,71 @@ +### Introduction +After you run the command on the profile page a basic setup is created for you, including this +tutorial and a few other files. These files include content describing some of the details on +how to format the content. + +### Adding support +If you used the script to generate the support files, you can skip this section. + +In your repository to add support you'll need the `support` directory, inside this directory +you will need to create a `gitdoc.json` file. This file contains details about the repository. +``` +$ mkdir support/ +$ touch support/gitdoc.json +``` +The other files in the `support` directory are optional, only `gitdoc.json` is required. + +The following sections describe the information needed in the files. + +### gitdoc.json +There are a few fields in this file that make it easy to give your viewers extra details about +the community, as well as the domain for premium repos. + +#### googleGroup +This is a field you can use to give your viewers a link to your google group. Just set the field +to the name of your google group, and we'll create the link. It isn't required though, you can +leave it out safely. + +#### irc +This is a field you can use to give your viewers the details to join your irc channel. To use it +set an `object` with two fields. One of the fields is `server`, this is the server address for the +irc network(e.g. `irc.freenode.net` for the freenode network). The next is the `channel` field, +this tells the viewers the specific channel for your community. The channel requires you to +include the prefix character though(e.g. #, &, +, !), since there are multiple. + +#### domain +This is a field you can use if your repository is premium. It tells us the name of the domain +for your repo, so we can get your repo if we detect a custom domain. You can ignore it, or just +set a placeholder if it's not premium yet. + +#### analytics +When you view the repo from a custom premium domain, if this field is given it'll include the +Google Analytics snippet to track page views. This value should be your GA web property ID. + +### changelog.md +This file is just a markdown file displaying the changelog for your repository. For details on +the markdown, view the default documentation created. This file can be safely ignored if you don't +want to include a changelog page. + +### faq.md +This file is just a markdown file displaying the frequently asked questions for your repository. +For details on the markdown, view the default documentation created. This file can be safely +ignored if you don't want to include a faq page. + +### tutorial.md +This file is just a markdown file displaying the tutorial for your repository. For details on the +markdown, view the default documentation created. This file can be safely ignored if you don't +want to include a tutorial page. + +### styles.css +This file is used when your repository is premium to display custom layouts for your viewers. It +can be safely ignored, or just as a place holder if the repo is not premium yet. + +### reference/ +This directory is used to hold the markdown files for the documentation/reference page. Every file +in this directory will be added as a section to the documentation with the section titled after +the file name, so make sure it's readable. + +### guide/ +This directory is used to hold the markdown files for the documentation/guide page. Every file in this +directory will be added as a section to the guide with the section titled after the file name, so +make sure it's readable. diff --git a/table_replication_consistency/table_replication_consistency.cpp b/table_replication_consistency/table_replication_consistency.cpp index e29fc0cd7..0ef68aa27 100644 --- a/table_replication_consistency/table_replication_consistency.cpp +++ b/table_replication_consistency/table_replication_consistency.cpp @@ -16,7 +16,7 @@ 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. -Author: Jan Lindström jan.lindstrom@skysql.com +Author: Jan Lindström jan.lindstrom@mariadb.com Created: 20-06-2013 Updated: diff --git a/table_replication_consistency/table_replication_consistency.h b/table_replication_consistency/table_replication_consistency.h index f900d1bf0..10d4451b6 100644 --- a/table_replication_consistency/table_replication_consistency.h +++ b/table_replication_consistency/table_replication_consistency.h @@ -16,7 +16,7 @@ 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. -Author: Jan Lindström jan.lindstrom@skysql.com +Author: Jan Lindström jan.lindstrom@mariadb.com Created: 20-06-2013 Updated: diff --git a/table_replication_consistency/table_replication_listener.cpp b/table_replication_consistency/table_replication_listener.cpp index 283b49984..6c1502d70 100644 --- a/table_replication_consistency/table_replication_listener.cpp +++ b/table_replication_consistency/table_replication_listener.cpp @@ -16,7 +16,7 @@ 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. -Author: Jan Lindström jan.lindstrom@skysql.com +Author: Jan Lindström jan.lindstrom@mariadb.com Created: 20-06-2013 Updated: */ diff --git a/table_replication_consistency/table_replication_listener.h b/table_replication_consistency/table_replication_listener.h index 2c1b31794..6cea875f4 100644 --- a/table_replication_consistency/table_replication_listener.h +++ b/table_replication_consistency/table_replication_listener.h @@ -16,7 +16,7 @@ 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. -Author: Jan Lindström jan.lindstrom@skysql.com +Author: Jan Lindström jan.lindstrom@mariadb.com Created: 20-06-2013 Updated: diff --git a/table_replication_consistency/table_replication_metadata.cpp b/table_replication_consistency/table_replication_metadata.cpp index b25a350ed..0c9a4161f 100644 --- a/table_replication_consistency/table_replication_metadata.cpp +++ b/table_replication_consistency/table_replication_metadata.cpp @@ -16,7 +16,7 @@ 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. -Author: Jan Lindström jan.lindstrom@skysql.com +Author: Jan Lindström jan.lindstrom@mariadb.com Created: 15-07-2013 Updated: */ diff --git a/table_replication_consistency/table_replication_metadata.h b/table_replication_consistency/table_replication_metadata.h index 910d63295..d29b5b9b1 100644 --- a/table_replication_consistency/table_replication_metadata.h +++ b/table_replication_consistency/table_replication_metadata.h @@ -16,7 +16,7 @@ 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. -Author: Jan Lindström jan.lindstrom@skysql.com +Author: Jan Lindström jan.lindstrom@mariadb.com Created: 15-07-2013 Updated: */ diff --git a/table_replication_consistency/table_replication_parser.cpp b/table_replication_consistency/table_replication_parser.cpp index 999a9b083..42c92efaf 100644 --- a/table_replication_consistency/table_replication_parser.cpp +++ b/table_replication_consistency/table_replication_parser.cpp @@ -16,7 +16,7 @@ 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. -Author: Jan Lindström jan.lindstrom@skysql.com +Author: Jan Lindström jan.lindstrom@mariadb.com Created: 20-06-2013 Updated: diff --git a/table_replication_consistency/table_replication_parser.h b/table_replication_consistency/table_replication_parser.h index 5a854e2f7..e60ad8576 100644 --- a/table_replication_consistency/table_replication_parser.h +++ b/table_replication_consistency/table_replication_parser.h @@ -16,7 +16,7 @@ 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. -Author: Jan Lindström jan.lindstrom@skysql.com +Author: Jan Lindström jan.lindstrom@mariadb.com Created: 20-06-2013 Updated: diff --git a/utils/skygw_utils.cc b/utils/skygw_utils.cc index 3699791c3..4a020d38e 100644 --- a/utils/skygw_utils.cc +++ b/utils/skygw_utils.cc @@ -320,6 +320,7 @@ mlist_t* mlist_init( list->mlist_nodecount_max = maxnodes; /** Set data deletion callback fun */ list->mlist_datadel = datadel; + if (name != NULL) { list->mlist_name = name; } @@ -345,6 +346,7 @@ mlist_t* mlist_init( CHK_MLIST_CURSOR(c); *cursor = c; } + list->mlist_versno = 2; /*< vresno != 0 means that list is initialized */ CHK_MLIST(list); return_list: diff --git a/utils/skygw_utils.h b/utils/skygw_utils.h index 309b9019f..6d2bc7b67 100644 --- a/utils/skygw_utils.h +++ b/utils/skygw_utils.h @@ -52,9 +52,7 @@ typedef struct mlist_st { bool mlist_deleted; size_t mlist_nodecount; size_t mlist_nodecount_max; /**< size limit. 0 == no limit */ -#if 1 size_t mlist_versno; -#endif bool mlist_flat; mlist_node_t* mlist_first; mlist_node_t* mlist_last;